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

ThingWorx Navigate is now Windchill Navigate Learn More

IoT & Connectivity Tips

Sort by:
import com.axeda.drm.sdk.Context import com.axeda.drm.sdk.device.ModelFinder import com.axeda.drm.sdk.device.Model import com.axeda.drm.sdk.device.DeviceFinder import com.axeda.drm.sdk.data.CurrentDataFinder import com.axeda.drm.sdk.device.Device import com.axeda.drm.sdk.data.HistoricalDataFinder import net.sf.json.JSONObject /* * DataItemEachDevice.groovy * * Find the current data item and historical data items for all assets in a given model. * * @param model_name        -   (REQ):Str name of the model. * @param data_item_name    -   (REQ):Str name of the data item to query on. * @param from_time         -   (REQ):Long millisecond timestamp to begin query from. * @param to_time           -   (REQ):Long millisecond timestamp to end query at. * * @note from_time and to_time should be provided because it limits the query size. * * @author Sara Streeter <sstreeter@axeda.com> */ def response = [:] // measure the script run time def timeProfiles = [:] def scriptStartTime = new Date() try { // getUserContext is supported as of release 6.1.5 and higher     final def CONTEXT = Context.getUserContext() // confirm that required parameters have been provided     validateParameters(actual: parameters, expected: ["model_name", "data_item_name", "from_time", "to_time"]) // find the model     def modelFinder = new ModelFinder(CONTEXT)     modelFinder.setName(parameters.model_name)     Model model = modelFinder.findOne() // throw exception if no model found     if (!model) {         throw new Exception("No model found for ${parameters.model_name}.")     } // find all assets of that model     def assetFinder = new DeviceFinder(CONTEXT)     assetFinder.setModel(model)     def assets = assetFinder.findAll() // find the current and historical data values for each asset //note: since device will be set on the datafinders going forward, a dummy device is set on instantiation which is not actually stored     def currentDataFinder = new CurrentDataFinder(CONTEXT, new Device(CONTEXT, "placeholder", model))     def historicalDataFinder = new HistoricalDataFinder(CONTEXT, new Device(CONTEXT, "placeholder", model))     historicalDataFinder.startDate = new Date(parameters.from_time as Long)     historicalDataFinder.endDate = new Date(parameters.to_time as Long) // assemble the response     assets = assets.collect { Device asset ->         currentDataFinder.device = asset         def currentValue = currentDataFinder.find(parameters.data_item_name)         historicalDataFinder.device = asset         def valueList = historicalDataFinder.find(currentValue?.dataItem)         [                 id: asset.id.value,                 name: asset.name,                 serialNumber: asset.serialNumber,                 model: [id: asset.model.id.value, name: asset.model.name],                 current_data: currentValue.asString(),                 historical_data: valueList.collect { [timestamp: it.getTimestamp().format("yyyyMMdd HH:mm"), value: it.asString()] }         ]     }     response = [result: [items: assets]] } catch (def ex) {     logger.error ex     response += [             error: [                     type: "Backend Application Error", msg: ex.getLocalizedMessage()             ]     ] } finally { // create and output the running time profile     timeProfiles << createTimeProfile("DataItemEachDevice", scriptStartTime, new Date())     response += [params: parameters, meta: [:], timeProfiles: timeProfiles] } return ['Content-Type': 'application/json', 'Content': JSONObject.fromObject(response).toString(2)] private Map createTimeProfile(String label, Date startTime, Date endTime) {     [             (label): [                     startTime: [timestamp: startTime.time, readable: startTime.toString()],                     endTime: [timestamp: endTime.time, readable: endTime.toString()],                     profile: [                             elapsed_millis: endTime.time - startTime.time,                             elapsed_secs: (endTime.time - startTime.time) / 1000                     ]             ]     ] } private validateParameters(Map args) {     if (!args.containsKey("actual")) {         throw new Exception("validateParameters(args) requires 'actual' key.")     }     if (!args.containsKey("expected")) {         throw new Exception("validateParameters(args) requires 'expected' key.")     }     def config = [             require_username: false     ]     Map actualParameters = args.actual.clone() as Map     List expectedParameters = args.expected     config.each { key, value ->         if (args.options?.containsKey(key)) {             config[key] = args.options[key]         }     }     if (!config.require_username) { actualParameters.remove("username") }     expectedParameters.each { paramName ->         if (!actualParameters.containsKey(paramName) || !actualParameters[paramName]) {             throw new IllegalArgumentException(                     "Parameter '${paramName}' was not found in the query; '${paramName}' is a reqd. parameter.")         }     } } Sample Output: {   "result": {     "items": [{       "id": 4240,       "name": "ASVM_9",       "serialNumber": "ASVM_9",       "model": {         "id": 1535,         "name": "SimVM4"       },       "current_data": "142.0",       "historical_data": [{         "timestamp": "20120331 17:00", "value": "142.0"       }, {         "timestamp": "20120331 16:59", "value": "143.0"       }, {         "timestamp": "20120331 16:59", "value": "144.0"       }, {         "timestamp": "20120331 16:58", "value": "145.0"       }, {         "timestamp": "20120331 16:58", "value": "146.0"       }, {         "timestamp": "20120331 16:57", "value": "147.0"       }, {         "timestamp": "20120331 16:57", "value": "148.0"       }, {         "timestamp": "20120330 19:30",         "value": "0.0"       }]     }, {       "id": 4246,       "name": "ASVM_12",       "serialNumber": "ASVM_12",       "model": {         "id": 1535,         "name": "SimVM4"       },       "current_data": "138.0",       "historical_data": [{         "timestamp": "20120331 17:00",        "value": "138.0"       }, {         "timestamp": "20120331 17:00",        "value": "139.0"       }, {         "timestamp": "20120331 16:59",        "value": "140.0"       }, {         "timestamp": "20120331 16:59",        "value": "141.0"       }, {         "timestamp": "20120331 16:59",        "value": "142.0"       }, {         "timestamp": "20120331 16:59",        "value": "143.0"       }, {         "timestamp": "20120330 19:32",         "value": "0.0"       }]      //      // MORE ASSETS HERE      //     }]   },   "params": {     "username": "sstreeter",     "from_time": "1332272219000",     "data_item_name": "CurrentStock",     "sessionid": "JOQ5I7ofRXYA-RnA37Vk93bRUH718yoFF5 9p0JbCnfyoHolFprf",     "model_name": "SimVM4",     "to_time": "1335469008000"   },   "meta": {},   "timeProfiles": {     "DataItemEachDevice": {       "startTime": {         "timestamp": 1335469168725,         "readable": "Thu Apr 26 19:39:28 GMT 2012"       },       "endTime": {         "timestamp": 1335469180569,         "readable": "Thu Apr 26 19:39:40 GMT 2012"       },       "profile": {         "elapsed_millis": 11844,         "elapsed_secs": 11.844       }     }   } }
View full tip
Users can install ThingWorx and KEPServerEX on the same PC or server. It is recommended to install KEPServerEX prior to installing ThingWorx in this case. For more information, see: Do I need to uninstall ThingWorx before installing KEPServerEX?
View full tip
We will host a live Expert Session: "Upgrade to Thingworx 9 – How to Plan / Evaluate Impacts" on January 12th 8h00 EST.   Please find below the description of the expert session and the registration link: Expert Session: Upgrade to Thingworx 9 – How to Plan / Evaluate Impacts Date and Time: January 12th 8h00 EST Duration: 1 hour Host: Ayush Tiwari - IoT Product Manager Registration Here: https://www.ptc.com/en/customer-success/expert-sessions-for-thingworx-foundation-webcasts    Description: This session will highlight the key points you should evaluate to properly plan your upgrade to Thingworx 9.   Existing Recorded sessions can be found on support portal using the keyword ‘Expert Sessions’. You can also suggest topics for upcoming sessions using this small form.   Here are some recorded sessions that might be of your interest. You can find recordings for the full library of webinars using the keyword ‘Expert Sessions’ in PTC support portal search.   Thingworx Flow Overview Flow is a powerful component of the ThingWorx platform.  This session will take the Flow discussion beyond basic applications and into more customized and complex solutions.​ This will focus on use cases, main features such as triggers, connector options, main enhancements for Thingworx 9.0 and a short demonstration   Recoding Link Top 5 items to check for Thingworx Performance Troubleshooting How to troubleshoot performance issues in a Thingworx Environment? Here we cover the top 5 investigation steps that will help you understand the source of your environment issues and allow better communication with PTC Technical Support     Recording Link
View full tip
  Step 5: Bind Industrial Tag   Now that you've established a connection, you can use ThingWorx Foundation to inspect all available information on ThingWorx Kepware Server.   ThingWorx Kepware Server includes some information by default to assist you with verifying a valid connection with ThingWorx Foundation.   Create New Thing   In ThingWorx Foundation, click Browse > Modeling > Industrial Connections.   Click IndConn_Server. At the top, click Discover. The Discover option is exclusive to Things inheriting the IndustrialGateway Thing Template and displays information coming from ThingWorx Kepware Server.   Expand Channel1. Click Device1. On the right, you’ll see Tag1 and Tag2, which are pre-defined Tags to assist with connectivity testing.   Click the checkbox next to Tag1. Click Bind to New Entity.   In the Choose Template pop-up, select RemoteThing and click OK.   Finalize New RemoteThing   You’ll now be in an interface to create a new Thing with a predefined Property based on ThingWorx Kepware Server Tag1.   Type IndConn_Tag1 in the Name field. In the Description field, enter an appropriate description, such as Thing with a property fed from an Kepware Server Tag. The Base Thing Template has been automatically set to RemoteThing. The Implemented Shapes has been automatically set to IndustrialThingShape.   If Project is not already set, search for and select PTCDefaultProject.   Click Save.   Test Connection   The IndConn_Tag1 Thing you created now has a Property with a value that will change with each update from ThingWorx Kepware Server.   The Tag1 we utilized is a 'ramp' and therefore, the value will increase at regular intervals.   At the top, click Properties and Alerts. Under Inherited Properties, you will see entries for both RemoteThing and IndustrialThingShape. The Property isConnected is checked, indicating a connection from Foundation to ThingWorx Kepware Server. The Property IndustrialThing has been automatically set to IndConn_Server. Notice the predefined Property named Channel1_Device1_Tag1.   Click Refresh repeatedly. You’ll see the value increase with each Refresh. This represents data being simulated in ThingWorx Kepware Server.   Step 6: Log to Value Stream   Now that you have explored the Properties of IndConn_Tag1, you’ve seen how ThingWorx Kepware Server feeds information to ThingWorx Foundation.   To get an even better indication of changes and confirm continued connectivity, we will log the changes to a Value Stream in order to record the values with a TimeStamp.   Create Value Stream   In ThingWorx Foundation, click Browse > Data Storage > Value Streams.   Click + New.   In the Choose Template pop-up, select ValueStream. Click OK. Type IndConn_ValueStream in the Name field. In the Description field, enter an appropriate description, such as Value Stream to record changes from ThingWorx Kepware Server. If Project is not already set, search for and select PTCDefaultProject. Click Save.   Bind Value Stream   Return to the IndConn_Tag1 Thing. At the top, select General Information. In the Value Stream field, search for and select IndConn_ValueStream.   At the top, select Properties and Alerts.   Click Channel1_Device1_Tag1. A new set of options will expand from the right.   Check the box for Persistent. Check the box for Logged.   In the top-right, click the Check button to close the expanded options. Click Save.   All changes to the Tag1 Property fed from ThingWorx Kepware Server are now stored and TimeStamped to the IndConn_ValueStream.     Step 7: Visualize the Data   We'll now create a Mashup to visualize the record of information from ThingWorx Kepware Server.   In ThingWorx Foundation, click Browse > Visualization > Mashups.   Click +New.   In the New Mashup pop-up, leave the default selections and click OK.   In the Name field, type IndConn_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, ensure the Widgets tab is selected.   In the Filter Widgets field at the top-left, type line. Drag-and-drop a Line Chart onto the central canvas area.     Add Data   At the top-right, ensure the Data tab is active.   Click the + button.   In the Entity Filter field, search for and select IndConn_Tag1. In the Services Filter field, type queryprop. Click the right-arrow button beside QueryPropertyHistory. The QueryPropertyHistory Service of the IndConn_Tag1 Thing will appear on the right in the Selected Services field. Check the box under Execute on Load in the Selected Services field.   Click Done. Note that the QueryPropertyHistory Service now appears on the right side Data tab. On the top-right Data tab, expand Things_IndConn_Tag1 > QueryPropertyHistory > Returned Data.   Drag-and-drop All Data from the QueryPropertyHistory Service from the right onto the Line Chart in the center.   In the Select Binding Target pop-up, select Data.   Configure Chart Properties   Click the Line Chart to select it. In the bottom-left Properties, type xaxisfield in the filter. Expand the drop-down for XAxisField.   Select timestamp. At the top, click Save. Click View Mashup. (You may have to enable pop-ups in your browser.)   The IndConn_Mashup will show you the recorded history of Property changes that came from ThingWorx Kepware Server.   Because the Tag1 Example is a ramp, you’ll notice a slowly-increasing value in the Line Chart.   Reload the Mashup's browser-tab to see the value increase even further.   NOTE: If the Mashup visualization is blank, confirm your connection to ThingWorx Kepware Server. Return to the Test Connection section of the "Bind Industrial Tag" step.     Step 8: Next Steps   Congratulations! You've successfully completed the Connect Industrial Devices and Systems guide.   You've learned how to:   Connect ThingWorx Kepware Server to ThingWorx Foundation Secure the connection with an Application Key Create an IndustrialGateway Thing Map ThingWorx Kepware Server Tags to ThingWorx Foundation Thing Properties Visualize Data from connected digital assets   Learn More   Capability Resource Connect Connect to an Allen-Bradley PLC   Additional Resources   For additional information on ThingWorx Kepware Server:   Resource Link Documentation Kepware documentation Support Kepware Support site
View full tip
Email an attachment using bytes from a FileInfo Parameters: fileId - the identifier to a FileInfo that has been previously uploaded to the FileStore filename - the name of the attachment toaddress - the email address to send to fromaddress - the email address to send from import com.axeda.drm.util.Emailer; import com.axeda.drm.sdk.contact.Email import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import static com.axeda.sdk.v2.dsl.Bridges.* import com.axeda.services.v2.FileInfoCriteria import org.apache.commons.io.IOUtils import java.security.MessageDigest try {   String fromaddress = parameters.fromaddress   String toaddress = parameters.toaddress   def fileId = parameters.fileId   def filename = parameters.filename   String subject = "Axeda Test Attachment"   String body = "<html><head/><body><p style='background:blue;'>This email has an attachment and a blue background.</p></body></html>"   def thefile = new File(filename)   def inputStream = fileInfoBridge.getFileData(fileId)   byte[] bytes = IOUtils.toByteArray(inputStream);   thefile.setBytes(bytes)   def random_hash = md5('r');   def contentType = "multipart/mixed; boundary=--\"$random_hash\"\r\n"   def htmlType = "text/html" sendEmail(fromaddress, toaddress, subject,  body, contentType, thefile, false, htmlType) } catch (Exception e) { logger.error(e.localizedMessage) } return true def md5(String s) {     MessageDigest digest = MessageDigest.getInstance("MD5")     digest.update(s.bytes);     new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0') } public void sendEmail(String fromAddress, String toAddress,String subject, String body, String encoding, File file, boolean compress, String mimeType) {     try {         Emailer.getInstance().send([new InternetAddress(toAddress)],new InternetAddress(fromAddress), subject,body, encoding, [file] as File[], compress, mimeType);     } catch (Exception ae) {         logger.error(ae.localizedMessage);     } }
View full tip
Still not sure what the reference benchmarks have to offer? Check out this short video abstract reviewing the purpose of the reference benchmarks, some notes on how to read the guide, and information about what these guides will have to offer. Then, check out the reference benchmark for remote monitoring here!   ~~
View full tip
  Step 4: Data Tables (cont.) Set Properties We now have the Thing with Properties that we want logged, the Service to do said logging, and the Data Table to where the values will be stored   At the top, click Properties and Alerts. Note Data_Table_Test_Thing’s Index_Property and Value_Property.   On the Index_Property line under the Value column, click the "Pencil" icon for Set value of property.   In the slide-out on the right, enter 1.   At the top-right, click the "Check" button for Set. On the Value_Property line under the Value column, click the "Pencil" icon for Set value of property. In the slide-out on the right, enter 10.   At the top-right, click the "Check" button for Set. At the top, click Save.     Store to Data Table At the top, click Services.   On the Add_Data_Table_Entry_Service line under the Execute column, click the "Play" icon for Execute service. A pop-up will open.   At the bottom-right, click Execute. At the bottom-right, click Done. Retrieve from Data Table Return to Test_Data_Table.   At the top, click Services. Scroll down and locate the QueryDataTableEntries built-in Service.   On the QueryDataTableEntries line, click the "Play" icon for Execute service. A pop-up will open. On the bottom-right of the pop-up, click Execute. Note that you should see a single entry, showing the Index_Field at 1 and the the Value_Field at 10   On the bottom-right, click Done. If so desired, you may repeat the previous steps to add additional entries to the Data Table. You will note that the Index and Value fields of the Data Table continue to change in each entry to whatever you have set. Utilizing the functionality of the QueryDataTableEntries built-in Service was just a way to show that the Index and Value items had been correctly logged to the external Data Table. If you wanted to visualize the Data Tables in a grid, it would be as simple as utilizing the Grid Widget and tying Test_Data_Table -> QueryDataTableEntries -> All Data to said Grid. Step 5: Info Tables Just like with Streams and Data Tables, an Info Table requires a Data Shape to format it. In this example, we'll actually use the exact same Data Shape we previously created for the Stream. Create Thing Info Tables are another way to perform non-time-series data storage within the ThingWorx platform. Info Tables used for storage are tied directly to a particular Thing. As such, they are somewhat non-optimal for situations where you’re wanting to aggregate data across multiple Things. Info Tables are a Property Base Type in ThingWorx, in the same manner as a Number, Integer, or String. On the ThingWorx Composer Browse tab, click Modeling > Things, + New.   In the Name field, enter Test_Info_Table_Thing. If Project is not already set, search for and select PTCDefaultProject. In the Thing Template field, search for and select GenericThing.   At the top, click Properties and Alerts. Click + Add. In the Name field, enter Info_Table_Property. Change the Base Type to INFOTABLE. In the Data Shape field, search for and select Test_Data_Shape. This is the same Data Shape we previously created for the Stream. We're just reusing it for formatting the Info Table. Check the Persistent checkbox.   At the top-right, click the "Check" button for Done. At the top, click Save.     Set First Value Now that we have a Thing with an Info Table Property (formatted by our Data Shape), you can set some values for later display in a Mashup. On the new Info_Table_Property line under the Value column, click the "Pencil" button for Set value of property.   On the new pop-up, click the + Add button.   In the Index_Field, enter 1. In the Value_Field, enter 11.   At the bottom-right of the pop-up, click Add. Set Second Value On the pop-up, click the + Add button. In the Index_Field, enter 2. In the Value_Field, enter 22.   At the bottom-right of the pop-up, click Add. Set Third Value On the pop-up, click the + Add button. In the Index_Field, enter 3. In the Value_Field, enter 33.   At the bottom-right of the pop-up, click Add.   At the bottom-right of the pop-up, click Save. At the top, click Save.     Create Mashup Now that we have a Thing with an InfoTable Property and some value-entries in said InfoTable, let's create a Mashup to display those values by using the Grid Widget. On the ThingWorx Composer Browse tab, click VISUALIZATION > Mashups, + New.   On the New Mashup pop-up, leave the defaults, and click OK.   In the Name field, enter Test_Info_Table_Mashup. If Project is not already set, search for and select PTCDefaultProject.  At the top, click Save.   At the top, click Design. With the Widgets tab selected in the top-left, drag-and-drop a Grid Advanced Widget onto the central Canvas area.     Bind Data On the far-right, ensure that the Data tab is selected. Note that you may have to expand this area from the far-right.   Click the + icon. The Add Data pop-up will appear.   In the Entity Filter field, search for and select Test_Info_Table_Thing. In the Services Filter field, enter getprop. Click the right arrow beside the GetPropertyValues Service. On the right under Selected Services, check the Execute on Load checkbox.   At the bottom-right of the pop-up, click Done. Note that Test_Info_Thing -> GetPropertyValues is now available under the Data tab at the far-right. Expand GetPropertyValues > Returned Data > All Data.   Drag-and-drop GetPropertyValues > Returned Data > All Data > Info_Table_Property onto the Grid Advanced Widget in the central Canvas area.   On the Select Binding Target pop-up, select Data.   At the top, click Save. At the top, click View Mashup.   The new Mashup displays all of the Index and Value fields you had previously entered. If you were to add additional entries to the Info Table Property and then refreshed the Mashup, you would see those additional entries as well.   Step 6: Next Steps Congratulations! In this guide, you've learned how to: Differentiate between data storage methods Create a Data Shape to format a Stream, Data Table, and Info Table Create a Value Stream and Stream to store Time-Series Data Create a Data Table and Info Table to store non-Time-Series Data Use built-in methods to log data to a Value Stream or Info Table Create custom Services which log data to a Stream or Data Table Confirm data storage value changes via a built-in Service or Grid Widget Learn More   We recommend the following resources to continue your learning experience:     Capability Guide 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 Data Storage Help Center
View full tip
  Use the C SDK to build an app that connects to ThingWorx with persistent bi-directional communication.     GUIDE CONCEPT   This project will introduce more complex aspects of the ThingWorx C SDK and help you to get started with development.   Following the steps in this this guide, you will be ready to develop your own IoT application with the ThingWorx C SDK.   We will teach you how to use the C programming language to connect and build IoT applications to be used with the ThingWorx Platform.   YOU'LL LEARN HOW TO   Establish and manage a secure connection with a ThingWorx server, including SSL negotiation and connection maintenance Enable easy programmatic interaction with the Properties, Services, and Events that are exposed by Entities running on a ThingWorx server Create applications that can be directly used with your device running the C programming language Basic concepts of the C Edge SDK How to use the C Edge API to build a real-world application How to utilize resources provided in the Edge SDK to help create your own application    Note: The estimated time to complete ALL 4 parts of this guide is 60 minutes.      Step 1: Completed Examples   Download the completed files for this tutorial: ThingWorx C Edge SDK Sample Files.zip.   This tutorial will guide you through working with the C SDK on differing levels. Utilize this file to see a finished example and return to it as a reference if you become stuck creating your own fully fleshed out application.   Keep in mind, this download uses the exact names for Entities used in this tutorial. If you would like to import this example and also create Entities on your own, change the names of the Entities you create.     Step 2: Environment Setup   In order to compile C code, you need a C compiler and the ThingWorx C Edge SDK. It will be helpful to have CMake installed on your system. CMake is a build tool that will generate make or project files for many different platforms and IDEs.   Operating System Notes Windows You will need a 3rd party compiler such as MinGW GCC, Cygwin GCC or you can follow these Microsoft instructions to download and use the Microsoft Visual C++ Build Tool. Mac Download the Apple Developer Tools. Linux/Ubuntu A compiler is included by default.   NOTE: You can use CMake, version 2.6.1 or later to build projects or make files, which then are used to build the applications that you develop with the C SDK.   Before you can begin developing with the ThingWorx C SDK, you need to generate an Application Key and modify the source code file. You can use the Create an Application Key guide as a reference.   Modify Source File   Extract the files from the C SDK samples zip file. At the top level of the extracted files, you will see a folder called examples. This directory provides examples of how to utilize the C SDK. Open a terminal, go to your workspace, and create a new directory. You can also just switch to the unzipped directory in your system. After you've created this directory in your workspace, copy the downloaded files and folders into your new directory. You can start creating your connection code or open the main.c source file in the examples\SteamSensor\src directory for an example.   Operating System Code Linux/Ubuntu gedit main.c OR vi main.c Mac open –e main.c Windows start main.c        5. Modify the Server Details section at the top with the IP address for your ThingWorx Platform instance and the Application Key you would like to use.   Change the TW_HOST definition accordingly. Change the TW_PORT definition accordingly. Change the TW_APP_KEY definition to the keyId value saved from the last step.   /* Server Details */ #define TW_HOST "https://pp-XXXXXXXXX.devportal.ptc.i" #define TW_PORT 80 #define TW_APP_KEY "e1d78abf-cfd2-47a6-92b7-37ddc6dd34618" NOTE: Using the Application Key for the default Administrator is not recommended. If administrative access is absolutely necessary, create a User and place the user as a member of Admins.   Compile and Run Code   To test your connection, you will only need to update the main.c in the SteamSensor example folder. CMake can generate Visual Studio projects, make build files or even target IDEs such as Eclipse, or XCode. CMake generates a general description into a build for your specific toolchain or IDE.   Inside the specific example folder you would like to run, ie SteamSensor. Create a directory to build in, for this example call it bin. mkdir bin  cd bin      5. Run the CMake command listed below. This assumes CMake is already on your PATH. cmake ..      6. CMake has now produced a set of project files which should be compatible with your development environment.   Operating System Command Note Unix make A set of make files Windows msbuild tw-c-sdk.sln /t:build A visual studio solution   NOTE: CMake does its best to determine what version of Visual Studio you have but you may wish to specify which version to use if you have more than one installed on your computer. Below is an example of forcing CMake to use a specific version of Visual Studio: cmake -G "Visual Studio 15 2017" .. If your version of Visual Studio or other IDE is unknown, use cmake -G to see a list of supported IDEs.   You also have the alternative of opening the tw-c-sdk.sln from within Visual Studio and building in this IDE.   NOTE: By default, CMake will generate a build for the creation of a release binary. If you want to generate a debug build, use the command-> cmake -DBUILD_DEBUG=ON ..       7. Once your build completes you will find the build products in the CMake directory (see example below). From here, open the project in your IDE of choice.   NOTE: You should receive messages confirming successful binding, authentication, and connection after the main.c file edits have been made.   Operating System Files Description Unix ./bin/src/libtwCSdk_static.a  Static Library Unix ./bin/src/libtwCSdk.so  Shared Library Unix ./bin/examples/SteamSensor/SteamSensor   Sample Application Windows .\bin\src\<Debug/Release>\twCSdk_static.lib  Static Library Windows .\bin\src\<Debug/Release>\twCSdk.dll  Shared Library Windows .\bin\examples\<Debug/Release>\SteamSensor\SteamSensor.exe  Sample Application     Step 3: Run Sample Code   The C code in the sample download is configured to run and connect to the Entities provided in the ThingWorxEntitiesExport.xml file. Make note of the IP address of your ThingWorx Composer instance. The top level of the exported zip file will be referred to as [C SDK HOME DIR].   Navigate to the [C SDK HOME DIR]/examples/ExampleClient/src directory. Open the main.c source file.   Operating System Command Linux/Ubuntu gedit main.c OR vi main.c Mac open –e main.c Windows start main.c   Modify the Server Details section at the top with the IP address for your ThingWorx Platform instance and the Application Key you would like to use. Change the TW_HOST definition accordingly.   NOTE: By default, TW_APP_KEY has been set to the Application Key from the admin_key in the import step completed earlier. Using the Application Key for the default Administrator is not recommended. If administrative access is absolutely necessary, create a user and place the user as a member of the Admins security group.   /* Server Details */ #define TW_HOST "127.0.0.1" #define TW_APP_KEY "ce22e9e4-2834-419c-9656-e98f9f844c784c"   If you are working on a port other than 80, you will need to update the conditional statement within the main.c source file. Search for and edit the first line within the main function. Based on your settings, set the int16_t port to the ThingWorx platform port. Click Save and close the file. Create a directory to build in, for this example call it bin.   Operating System Command Linux/Ubuntu mkdir bin Mac mkdir bin Windows mkdir bin   Change to the newly created bin directory.   Operating System Command Linux/Ubuntu cd bin Mac cd bin Windows cd bin   Run the CMake command using your specific IDE of choice.    NOTE: Include the two periods at the end of the code as shown below. Use cmake -G to see a list of supported IDEs.   cmake ..   Once your build completes, you will find the build products in the bin directory, and you can open the project in your IDE of choice. NOTE: You should receive messages confirming successful binding, authentication, and connection after building and running the application    10. You should be able to see a Thing in your ThingWorx Composer called SimpleThing_1 with updated last Connection and isConnected properties. SimpleThing_1 is bound for the duration of the application run time                                                                                                                                                                                The below instructions will help to verify the connection.   Click Monitoring. Click Remote Things from the list to see the connection status.   You will now be able to see and select the Entity within the list.   Step 4: ExampleClient Connection   The C code provided in the main.c source file is preconfigured to initialize the ThingWorx C Edge SDK API with a connection to the ThingWorx platform and register handlers. In order to set up the connection, a number of parameters must be defined. This can be seen in the code below.   #define TW_HOST "127.0.0.1" #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c #if defined NO_TLS #define TW_PORT = 80; #else #define TW_PORT = 443; #endif The first step of connecting to the platform: Establish Physical Websocket, we call the   twApi_Initialize function with the information needed to point to the websocket of the ThingWorx Composer. This function:   Registers messaging handlers Allocates space for the API structures Creates a secure websocket   err = twApi_Initialize(hostname, port, TW_URI, appKey, NULL, MESSAGE_CHUNK_SIZE, MESSAGE_CHUNK_SIZE, TRUE); if (TW_OK != err) { TW_LOG(TW_ERROR, "Error initializing the API"); exit(err); }   If you are not using SSL/TLS, use the following line to test against a server with a self-signed certificate:   twApi_SetSelfSignedOk();   In order to disable HTTPS support and use HTTP only, call the twApi_DisableEncryption function. This is needed when using ports such as 80 or 8080. A call can be seen below:   twApi_DisableEncryption();   The following event handlers are all optional. The twApi_RegisterBindEventCallback function registers a function that will be called on the event of a Thing being bound or unbound to the ThingWorx platform. The twApi_RegisterOnAuthenticatedCallback function registered a function that will be called on the event the SDK has been authenticated by the ThingWorx Platform.  The twApi_RegisterSynchronizeStateEventCallback function registers a function that will be called after binding and used to notify your application about fields that have been bound to the Thingworx Platform.   twApi_RegisterOnAuthenticatedCallback(authEventHandler, TW_NO_USER_DATA); twApi_RegisterBindEventCallback(NULL, bindEventHandler, TW_NO_USER_DATA); twApi_RegisterSynchronizeStateEventCallback(NULL, synchronizeStateHandler, TW_NO_USER_DATA);   NOTE: Binding a Thing within the ThingWorx platform is not mandatory, but there are a number of advantages, including updating Properties while offline.   You can then start the client, which will establish the AlwaysOn protocol with the ThingWorx Composer. This protocol provides bi-directional communication between the ThingWorx Composer and the running client application. To start this connection, use the line below:   err = twApi_Connect(CONNECT_TIMEOUT, RETRY_COUNT); if(TW_OK != err){ exit(-1); }     Click here to view Part 2 of this guide
View full tip
  Use the Edge MicroServer (EMS) to simulate an engine with vibration sensors.   GUIDE CONCEPT   The Edge MicroServer (EMS) facilitates connectivity from Edge devices to ThingWorx Foundation.   It’s often easier, though, to start development with simulated Edge values rather than hooking up sensors.   This guide will show you how to simulate vibration values of an engine using the EMS.     YOU'LL LEARN HOW TO   Modify an EMS Template Provision Thing Properties and Values from an EMS rather than Foundation Send information from an EMS to Foundation Store large amounts of data in an InfoTable Property Create a simulator for testing   NOTE:  The estimated time to complete all parts of this guide is 30 minutes.     Step 1: Scenario   MotorCo manufactures, sells, and services commercial motors.   Recently, MotorCo has been developing a new motor, and they already have a working prototype.   However, they’ve noticed that the motor has a chance to FAIL CATASTROPHICALLY if it’s not properly serviced to replace lost grease on a key moving part.     In order to prevent this type of failure in the field, MotorCo has decided to instrument their motors with sensors which record vibration.   The hope is that these sensors can detect certain vibrations which indicate required maintenance before a failure occurs.   In this guide, you’ll begin this monitoring process by using ThingWorx Foundation to monitor and record vibration data from the prototype motor. In particular, you will learn how to provision Thing Properties and Values from an EMS, as well as how to permanently store these values for analysis in an Info Table Property.   These types of modifications to an EMS can be extremely helpful for the automotive segment in particular. For instance, each car that comes off the factory line could have custom, auto-generated EMS scripting that would dynamically create Foundation information for each car in the fleet. This could be a massive time-savings versus manually generating Thing Properties directly within Foundation.   Because the motor is still in the process of being instrumented with sensors, you’ll get all the functionality in-place beforehand by constructing a motor simulator using the Edge MicroServer (EMS).     Step 2: Modify config.lua   In the previous Use the Edge MicroServer (EMS) to Connect to ThingWorx  guide, you installed the EMS on a Windows PC, configured it to talk to ThingWorx Foundation, and then created an EdgeThing on Foundation to complete the connectivity.   This guide assumes that you have already completed that Windows EMS guide and have an active EMS connection to the EdgeThing.   Perform the following steps to modify this connection to increase the task rate of the EMS, which we'll use in the following steps to update Properties more quickly.   On your Windows PC, select the Windows PowerShell window where the luaScriptResource.exe program is running.   Type Ctrl-C to close the luaScriptResource.exe operation, i.e. hold the Control key and hit the C key.   Minimize the luaScriptResource.exe PowerShell window, and activate the wsemse.exe PowerShell window.   Type Ctrl-C to close the wsems.exe operation.   Return to Foundation, and note that EdgeThing is not connected.   Navigate to the C:\CDEMO_EMSE\etc directory.   Open config.lua in your prefered text-editor.   Change scanRate to 1000. Add the following line below the scanRate line: taskRate = 1000,   The final code of config.lua should be the following Note that the EMS may have slightly modified your config.lua file, such as adding a data_security_key line. Leave these EMS-generated modifications alone. scripts.log_level = "WARN" scripts.script_resource_ssl = false scripts.script_resource_authenticate = false scripts.EdgeThing = { file = "thing.lua", template = "YourEdgeThingTemplate", scanRate = 1000, taskRate = 1000, sw_update_dir = "C:\\CDEMO_EMS\\updates" } Save the config.lua file.     Click here to view Part 2 of this guide.
View full tip
    Step 6: Map Data   Now that the event is created, we need to map the Properties of EdgeThing to the fields required to invoke an Analysis Job.   We'll start with the Inputs.   Select the previously-created Event, and click Map Data....   Click Inputs Mapping.   In Source Type, select Thing. In Source, search for and select EdgeThing.   On the left, scroll down and select s1_fb1. Note that you do NOT want the s1_fb1 that is part of the InfoTable Property, because the Info Table Property only stores recorded data, not live data. On the right, select _s1_fb1, the first frequency band required for the Model to make a prediction.   Click the Map button in the center.   Repeat this mapping process for for s1_fb2 through s1_fb5.   Map causalTechnique to causalTechnique in the same manner. This is a String Property in EdgeThing with a Default Value of "FULL_RANGE". Map goalField to goalField in the same manner. This is a String Property in EdgeThing with a Default Value of "low_grease".   Map Results   Now that the Inputs are mapped, we also want to map the Results.   Click Results Mapping on the left.   Map _low_grease to Result_low_grease. Map _low_grease_mo to Result_low_grease_mo.   Click Close to close the mapping pop-up.   Enable Event   Now that we've done the mapping from Foundation to Analytics, let's Enable the Analysis Event so that it can automatically generate and process Analysis Jobs. Select the mapped Analysis Event. Select Enable.   Now that you have enabled the Analysis Event, the new data will be submitted to Analytics Manager whenever EdgeThing's s1_fb1 Property changes.   An Analysis Job will automatically run, with a predictive score sent back and stored in EdgeThing's Result_low_grease (Boolean) and Result_low_grease_mo (Number) Properties.     Step 7: Check Jobs   In this step, we'll confirm that the automatic analysis of information coming from remote devices is operational.   On the ThingWorx Composer Analytics tab, click Analytics Manager > Analysis Jobs.   Uncheck Filter Completed Jobs.   Select a Job and click View.... Click Results.   NOTE: You will see true or false, corresponding to either a low grease or no low grease condition. Using this technology, you could create a paid customer service, where you offered to monitor remote engines, in return for automatically shutting them down before they experience catastrophic engine failure.   For that example implementation, you would utilize the EdgeThing.Result_low_grease BOOLEAN Property to trigger other actions.   For instance, you could create an Alert Event which would be triggered on a true reading.   You could then have a Subscription which paid attention to that Alert Event, and performed an action, such as sending an automatic shutdown command to the engine when it was experiencing a likely low grease event.   NOTE: We recommend that you return to the ThingWorx Composer Analytics > Analytics Manager > Analysis Events tab and Disable the Event prior to continuing. Since the simulator generates an Event every ~1 seconds, this can create a large number of Events, which can fill up your log.       Step 8: Next Steps   Congratulations. You've completed the Manage an Engine Analytical Model guide. In this guide you learned how to:   Define an Analysis Provider that uses the built-in Analytics Server Connector Publish a Model from Analytics Builder to Manager Create an Analysis Event which takes data from ThingWorx Foundation and decides whether or not a failure is likely   The next guide in the Vehicle Predictive Pre-Failure Detection with ThingWorx Platform learning path is Engine Failure-Prediction GUI.   Learn More   We recommend the following resources to continue your learning experience:    Capability     Guide Build Implement Services, Events, and Subscriptions Guide   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource              Link Community Developer Community Forum Support Analytics Manager Help Center      
View full tip
Beginning with version 8.4.0 ThingWorx Analytics Server can now automatically create metadata (Json file) based on the uploaded csv. file. Underneath video demonstrates the steps for automated metadata detection.
View full tip
  We are counting down the days for you—developers, technologists, futurists—to witness the unparalleled power of PTC’s technology. Hosted by PTC, LiveWorx is the world’s leading digital transformation event to equip you with the knowledge, power and tools you need to begin or accelerate your company’s digital transformation.   I’m excited to share that I will be presenting a breakout session on June 11 th , at 1:15pm EST, around a brand-new functionality we’re offering to improve your ability to manage and deploy your ThingWorx applications.   Want to learn more? Attend LiveWorx 2019 or learn about our livestream options. However you choose to attend, it’s an event that I’m pretty amped for and I can’t wait for you to be, too.   Hope to see you there—it’d be great to meet you in person!   Stay connected, Kaya  
View full tip
This video concludes Module 6: Predictive Models & Model Validation of the ThingWorx Analytics Training videos. 
View full tip
    Step 3: Streams (cont.) Store to Stream Now that the Stream, the Thing (and its Properties), and the Thing's Service are all in place, we can execute the Service (along with some Property changes) to demonstrate that the values are getting archived externally to the Stream. At the top, click Properties and Alerts. Note the previously-created Index_Property and Value_Property.   For Index_Property's Value column, click the "pencil" icon for Set value of property.   In the slide-out on the right, enter 1.   At the top-right, click the "Check" button for Set. For Value Property, click the "Pencil" icon for Set value of property.   In the slide-out on the right, enter 10.   At the top-right, click the "Check" button for Set. At the top, click Save.   With the Thing's Properties set to new values, you can now call your custom Service to store those values to the external Stream (along with an auto-generated timestamp). At the top, click Services.   On the Add_Stream_Entry_Service line, click the "Play" button for Execute Service.   At the bottom-right of the pop-up, click the Execute button.   At the bottom-right, click the Done button.   Retrieve from Stream To confirm that our Thing's custom Service is correctly logging our Property values, we'll now use a built-in Service of the Stream to retrieve the stored values. This same QueryStreamEntriesWithData Service could alternately be used to populate various Mashup Widgets to view the data in a more convenient format. Return to the Test_Stream Entity.   On the top, click Services.   Scroll down and locate the QueryStreamEntriesWithData Service's Execute service button.   At the bottom-right of the pop-up, click Execute. Note that you should see a single entry, showing the Index_Field at 1, the Value_Field at 10, and a timestamp of when the information was pushed to the Stream.   At the bottom-right, click Done. To further confirm external storage to the Stream, you may repeat the previous steps to confirm additional Property Value Storage with timestamping. Furthermore, you could create a Mashup utilizing either the Time-Series Chart or a Grid to display the data stored within the Stream. Step 4: Data Tables Just like with Streams, you also need a Data Shape to format a Data Table. In this example, we'll actually use the exact same Data Shape we previously created for the Stream. Create Data Table Both Data Tables and Info Tables may be appropriate for your non-time-series mass data storage needs. However, a Data Table is not tied to a Thing as an Info Table Property would be. If your non-time-series information is coming from multiple different sources, then it would generally be appropriate to use a Data Table. On the ThingWorx Composer Browse tab, click Data Storage > Data Tables, + New. On the Choose Template pop-up, select DataTable, and click OK. In the Name field, enter Test_Data_Table If Project is not already set, search for and select PTCDefaultProject. In the Data Shape field, search for and select Test_Data_Shape. This is the same Data Shape we previously created for the Stream. We're just reusing it for formatting the Data Table.  At the top, click Save. Create Thing Now that we have a Data Table, let's create a Thing with some Properties that we'll eventually log to the external Data Table. On the ThingWorx Composer Browse tab, click MODELING -> Things, + New. In the Name field, enter Data_Table_Test_Thing. If Project is not already set, search for and select PTCDefaultProject. In the Thing Template field, search for and select GenericThing. At the top, click Properties and Alerts. Click + Add. In the Name field, enter Index_Property. Change the Base Type to Integer. Check the Persistent checkbox. At the top, click the "Check with a +" button for Done and Add. In the Name field, enter Value_Property. Change the Base Type to Number. Check the Persistent checkbox. At the top-right, click the "Check" button for Done. Create Service We now have both a Data Table and a Thing with Properties that we want logged. Now we need to create a Service which does the logging. At the top, click Services. Click + Add. In the Name field, enter Add_Data_Table_Entry_Service. Under New Service on the left, click the Snippets tab. In the Filter field, type data table. Expand the Stream, Blog, Data Table section. A pop-up will open. Beside Add/Update Data Table, click the right arrow. In the Search Data Tables field, type test. Select Test_Data_Table. Note that a section of Javascript code has now been added to the Script window. Click the green Insert Code Snippet button. Modify Snippet On the 6th line of code, double-click undefined to select it. On the left, expand the Me/Entities tab. Under the Me/Entities tab, expand Properties. Note that this is not the Properties and Alerts at the top of Composer Click the right arrow beside Value_Property. Note that undefined has been replaced by me.Value_Property. On the 7th line of code, double-click the remaining undefined to select it. Click the right arrow beside Index_Property. Note that the second undefined has been replaced by me.Index_Property.   Click Done to stop editing the custom Service.   At the top, click Save.     Click here to view Part 4 of this guide.
View full tip
This code snippet shows how to add an existing Device to an existing DeviceGroup using a custom Groovy script executed by the Scripto web service. To call the script create a URL of the following form: http://<HOST>/services/v1/rest/Scripto/execute/addDeviceToDeviceGroup?us... NOTE: Text in angled brackets (< >) indicates a variable. Alternatively, this script can be called by an Expression Rule using the following form: If: Registration.first Then: ExecuteCustomObject("addDeviceToDeviceGroup","<ASSET_ID>","<GROUP_NAME>") It is worth noting that it is important when creating the Groovy script that the parameters be created in the order of the parameter list. import net.sf.json.JSONObject import com.axeda.drm.sdk.device.DeviceGroupFinder import com.axeda.drm.sdk.device.DeviceGroup import com.axeda.drm.sdk.Context import com.axeda.common.sdk.id.Identifier import com.axeda.drm.sdk.device.DeviceFinder def response = [:], status try {   if (parameters.assetId == null) { throw new IllegalArgumentException("parameter 'assetId' was not provided.")}   if (parameters.groupName == null) { throw new IllegalArgumentException("parameter 'groupName was not provided.")}   final def CONTEXT = Context.create(parameters.username)   def dgf = new DeviceGroupFinder(CONTEXT)   dgf.setName(parameters.groupName)   def group = dgf.find()   if (group == null) {     logger.error "could not retrieve group with name of '${parameters.groupName}'"     throw new Exception("could not retrieve group with id of '${parameters.groupName}'")   }   def df = new DeviceFinder(CONTEXT)   df.setId(new Identifier(parameters.assetId))   def device = df.find()   if (device == null) {     logger.error "could not retrieve asset with id of '${parameters.assetId}'"     throw new Exception("could not retrieve asset with id of '${parameters.assetId}'")   }   group.addDevice(device)   group.store()   // do a check to make sure the device is associated with the group.   group = dgf.find()   def devices = group.getDevices()   status = devices.contains(device) ? "success" : "failure"   // prepare the response.   response = [parameters: parameters, status: status] } catch (def e) {   logger.error e.getMessage()   response = [faultcode: e.getCause(), faultstring: e.getMessage()] } return ['Content-Type': 'application/json', 'Content': JSONObject.fromObject(response).toString(2)];
View full tip
    Step 5: Tie Data to Widgets   The Mashup now has access to the backend data via get/set Data Services.   In this step, you will tie these Data Services to the Checkbox Widgets to pull and push information.   Click the Data tab in the upper right   Under GetProperties, click and drag the arrow next to Channel2_myPLC_Coil2 onto the Left Checkbox. On the Select Binding Target pop-up, click State.   Click the Data tab again Drag Channel2_myPLC_Coil3 onto the right Checkbox. On the Select Binding Target pop-up, click State.   Enable Automatic Updates   The GetProperties Mashup Data Service will now propagate the State of Coil2 and Coil3 from the PLC onto these Checkbox Widgets.   The GetProperties Service will be called automatically when the Mashup loads, so the Checkboxes states will be accurate on initial viewing.   However, the backend data state changes, you will need the GetProperties Service to be automatically called again to update the Checkbox Widgets.   Fortunately, it is simple to trigger this behavior.   Click the Data tab Click GetProperties to select it.   On the right of the Mashup Builder, Click the Data Properties tab     Click the Automatically Update Values checkbox   Allow Bidirectional Sets   You also want to enable bi-directional communication, not only displaying the current value of the PLC, but also setting it via the Mashup GUI.   The SetProperties Mashup Data Service can accomplish this.   Click the Right Checkbox to select it.   Click the Checkbox Widget's top-left drop-down menu to expose the available options.   Drag State over the Data tab to expand it. Drop onto SetProperties > Channel2_myPLC_Coil3.   Click the right Checkbox drop-down menu again.   Click Configure Bindings.   Click the down arrow to the right of Changed.   Click Add Trigger Service. Click the Data tab. Select the setProperties check box.   Click Next to close the Trigger Services window. Click Done to close the Configure Bindings pop-up. At the top, click Save.     Step 6: View Mashup    Your Mashup is now complete with two Checkbox Widgets and connections from those Widgets to the backend data.   The left Checkbox represents Coil2, and will change its state depending on whether you have touched the lead to the appropriate input on the PLC.   The right Checkbox represents Coil3, and will display the current status as well as allow you to set the status of Output Coil 3 via checking or unchecking the box.   At the top, click View Mashup to display your web application. You may need to set your browser to allow pop-ups.     Select the right checkbox. Note how the PLC's Output Coil 3 will immediately turn on.   Touch the lead to the PLC's I-02, i.e. Input 2. The left checkbox will indicate the status of Input 2 within a couple of seconds. Step 7: Troubleshooting   If the connection to the PLC stops working and there is a Thumbs Down icon next to your properties, the ThingWorx Kepware Server trial edition drivers are not connected to your PLC. The trial edition stops running after 2 hours and must be stopped and restarted. Right-click on ThingWorx Kepware Server icon in system tray.     Click Stop Runtime service. Wait a minute for the process to stop, then click Start Runtime service. If Connected Components Workbench does not connect to PLC, check the IP address of the PLC using RS Linx Classic software that was installed as part of Connected Components Workbench. RS Linx Classic is located Start > All Programs > Rockwell Software > RSLinx > RSLinx Classic Click AB_ETHIP-1, Ethernet and IP addresses of connected PLCs will be discovered NOTE: A changed PLC IP Address (typically seen through Connected Components Workbench) will require an IP Address change in ThingWorx Kepware Server settings.     Step 8: Next Steps   Congratulations! You've successfully completed the Visualize an Allen-Bradley PLC guide.   In addition, assuming you have been utilizing this guide as part of the Rockwell Automation Learning Path, this represents the end of your journey.   You've learned how to:   Create a Mashup Add Widgets Access backend data via Mashup Data Services Tie data to Widgets Create a simple web application that monitors and controls a PLC   This is the last guide in the Using an Allen-Bradley PLC with ThingWorx learning path. Learn More   Capability Resource Analyze Monitor an SMT Assembly Line Additional Resources   For additional information on ThingWorx Kepware Server:   Resource Link Documentation Kepware documentation Support Kepware Support site
View full tip
Recently I have been accompanying an integration partner and end customer around an issue experienced with ThingWorx resource exhaustion.  Early on it seemed like this was an issue with the ThingWorx Azure IoT Hub Connector as it would freeze up and become unresponsive.  Following a root cause analysis it became clear that it was actually caused by a lack of a number of standard cloud design patterns, which if used would have automatically adapted operation of the overall solution to be far more resilient as well as resource optimized.   The way that the logic was structured, it prioritized job execution on entities with the oldest last success time and would continue to retry these executions (IoT Direct Methods) every few seconds until successful.  There were a number of problems here, but I'll unpack a few in order to tie the problem to the solution via design patterns.   1) No exception handling When the direct method execution failed/timed out or the system reported being unable to execute the remote service, this response was not used to adapt the solutions behavior. 2) No backoff retry mechanism As exceptions were not caught, an adaptive retry mechanism with incremental or exponential backoff could not be leveraged to limit the impact of the build up of the failing retries. 3) No exception tracking Tracking that exceptions were occurring and counting them would allow powering an exponential backoff retry algorithm (with jitter), a Cancel or Circuit Breaker pattern (stop doing something which is just broken), as well as provided alerting to address specific areas of the distributed solution experiencing issues. 4) Conflicting priorities It was interesting to see the manifestation of the conflicting interests of wanting to ensure checks and balances (had all needed data) and system resiliency.  Retries and resource usage built up exponentially due to the transient error instead of backing them off.  Trying so hard to get the needed data from failing sensors meant that operational sensors were deprioritized and their data was not received either - spreading the localized issue to the whole system.   Around the time that I shared my recommendations and some examples of how to make the solution more resilient, one of my technical colleagues at Microsoft shared some extremely interesting and relevant design patterns documented by Microsoft as a part of the "Microsoft Azure Well-Architected Framework".  This framework with included Design Patterns for specific cloud application goals allows applying well-known industry standard approaches to dealing with the challenges of large scale distributed enterprise systems (reliability, performance, cost optimization).   She later then shared this blog post describing exactly the exponential backoff retry with jitter pattern which we had together recommended to the systems integrator.   What's interesting for us ThingWorx people is that this framework from Microsoft is about well-architected cloud solutions and does not specifically reference the Azure stack, and as such many of these approaches and design practices can be employed in your ThingWorx applications.  What are you waiting for?  Go check them out!
View full tip
This demo walks through how Range Count works. The Range Count service calculates the difference between the maximum and minimum value.  Agenda of the demo: 1. Create a demo Thing 2. Add a new property to the Thing 3. Add the property statistical calculation type Range Count to the Thing 4. Validate the statistical calculation service via the added calculation type Range Count 5. Validate the statistical calculation service via the Service QueryTimedValuesForProperty      
View full tip
  Step 3: Run Sample Code The C code in the sample download is configured to run and connect to the Entities provided in the ThingWorxEntitiesExport.xml file. Make note of the IP address of your ThingWorx Composer instance. The top level of the exported zip file will be referred to as [C SDK HOME DIR]. Navigate to the [C SDK HOME DIR]/examples/ExampleClient/src directory. Open the main.c source file. Operating System          Command Linux/Ubuntu gedit main.c OR vi main.c Mac open –e main.c Windows start main.c Modify the Server Details section at the top with the IP address for your ThingWorx Platform instance and the Application Key you would like to use. Change the TW_HOST definition accordingly. NOTE: By default, TW_APP_KEY has been set to the Application Key from the admin_key in the import step completed earlier. Using the Application Key for the default Administrator is not recommended. If administrative access is absolutely necessary, create a user and place the user as a member of the Admins security group.   /* Server Details */ #define TW_HOST "127.0.0.1" #define TW_APP_KEY "ce22e9e4-2834-419c-9656-e98f9f844c784c" If you are working on a port other than 80, you will need to update the conditional statement within the main.c source file. Search for and edit the first line within the main function. Based on your settings, set the int16_t port to the ThingWorx platform port. Click Save and close the file. Create a directory to build in, for this example call it bin. Operating System           Command Linux/Ubuntu mkdir bin Mac mkdir bin Windows mkdir bin Change to the newly created bin directory. Operating System          Command Linux/Ubuntu cd bin Mac cd bin Windows cd bin Run the CMake command using your specific IDE of choice. NOTE: Include the two periods at the end of the code as shown below. Use cmake -G to see a list of supported IDEs.         cmake ..​           Once your build completes, you will find the build products in the bin directory, and you can open the project in your IDE of choice. NOTE: You should receive messages confirming successful binding, authentication, and connection after building and running the application. You should be able to see a Thing in your ThingWorx Composer called SimpleThing_1 with updated lastConnection and isConnected properties. SimpleThing_1 is bound for the duration of the application run time.     The below instructions will help to verify the connection. Click Monitoring. Click Remote Things from the list to see the connection status.   You will now be able to see and select the Entity within the list.   Step 4: ExampleClient Connection The C code provided in the main.c source file is preconfigured to initialize the ThingWorx C Edge SDK API with a connection to the ThingWorx platform and register handlers. In order to set up the connection, a number of parameters must be defined. This can be seen in the code below. #define TW_HOST "127.0.0.1" #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c #if defined NO_TLS #define TW_PORT = 80; #else #define TW_PORT = 443; #endif The first step of connecting to the platform: Establish Physical Websocket, we call the twApi_Initialize function with the information needed to point to the websocket of the ThingWorx Composer. This function: Registers messaging handlers Allocates space for the API structures Creates a secure websocket err = twApi_Initialize(hostname, port, TW_URI, appKey, NULL, MESSAGE_CHUNK_SIZE, MESSAGE_CHUNK_SIZE, TRUE); if (TW_OK != err) { TW_LOG(TW_ERROR, "Error initializing the API"); exit(err); } If you are not using SSL/TLS, use the following line to test against a server with a self-signed certificate: twApi_SetSelfSignedOk(); In order to disable HTTPS support and use HTTP only, call the twApi_DisableEncryption function. This is needed when using ports such as 80 or 8080. A call can be seen below: twApi_DisableEncryption(); The following event handlers are all optional. The twApi_RegisterBindEventCallback function registers a function that will be called on the event of a Thing being bound or unbound to the ThingWorx platform. The twApi_RegisterOnAuthenticatedCallback function registered a function that will be called on the event the SDK has been authenticated by the ThingWorx Platform. The twApi_RegisterSynchronizeStateEventCallback function registers a function that will be called after binding and used to notify your application about fields that have been bound to the Thingworx Platform. twApi_RegisterOnAuthenticatedCallback(authEventHandler, TW_NO_USER_DATA); twApi_RegisterBindEventCallback(NULL, bindEventHandler, TW_NO_USER_DATA); twApi_RegisterSynchronizeStateEventCallback(NULL, synchronizeStateHandler, TW_NO_USER_DATA); NOTE: Binding a Thing within the ThingWorx platform is not mandatory, but there are a number of advantages, including updating Properties while offline.   You can then start the client, which will establish the AlwaysOn protocol with the ThingWorx Composer. This protocol provides bi-directional communication between the ThingWorx Composer and the running client application. To start this connection, use the line below:   err = twApi_Connect(CONNECT_TIMEOUT, RETRY_COUNT); if(TW_OK != err){ exit(-1); }   Click here to view Part 3 of this guide.   
View full tip
  Build a Predictive Analytics Model - Video Guide   This project will introduce ThingWorx Analytics Builder via a convenient video-guide. Following the steps in this video, you will create an analytical model, and then refine it based on further information from the Analytics platform. We will teach you how to determine whether or not a model is accurate and how you can optimize both your data inputs and the model itself.     ThingWorx Analytics Server Installation with SSL   This video demonstrates the installation of Analytics Server with SSL protections enabled. It includes information about generating the necessary certificates and truststores to enable SSL for each component that connects with the server.     ThingWorx Platform Analytics Installation with SSL   This video demonstrates the Platform Analytics installation with SSL protections enabled. It provides information about generating the necessary certificates and truststores to enable SSL for all connected components, including RabbitMQ and Flink.     Toolbar Widget | ThingWorx 9   Watch this video to learn how to add a Toolbar widget to a mashup in ThingWorx. You'll learn how to define actions using a data service and create bindings to control and configure a Grid widget.     ThingWorx SSO: Login demonstration from Azure AD to ThingWorx   This video demonstrates the ThingWorx SSO login procedure using Azure AD. The login procedure is shown from a user point of view. Then a behind the scenes view looks at the design in ThingWorx Composer.     Menu Bar Widget ThingWorx 9   Watch this video to learn how to create a mashup layout that uses a Menu Bar widget for navigation. You'll learn how to create a layout, define menu items, and configure the widget.     ThingWorx AD FS SSO Setup   This video provides a walk-through of the steps required to set up SSO for ThingWorx in an environment where AD FS is both the CAS and the IdP. The focus is on the AD FS setup steps.     Create Your Application UI   Following the steps in this video-guide, you will learn how to use the ThingWorx Mashup Builder 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 requirement     Get Started with ThingWorx for IoT   Explore the ThingWorx Foundation Internet-of-Things application building platform in a convenient, instructional video guide format.     Thingworx Mashup 101 - Do's and Don'ts   This session covers the most common and useful tips about how to correctly use Mashup builder, Widgets and Layouts – and what to avoid - to create applications with good principles of UI/UX and easier to maintain.     What's New in ThingWorx 9.1   The industry’s most complete IIoT platform just got better. Loaded with a full range of new and updated features and functionality, you can expect powerful platform capability enhancements across the board.       Standardize Connectivity to Devices, Applications, & Systems for Centralized IIot Data   You can’t implement IIoT solutions if you can’t connect to your assets, but in complex environments connectivity can seem like an insurmountable challenge. ThingWorx makes it easy to establish standardized connectivity, so you can create a secure, single-source for accessing industrial data across your IT and OT systems     Bar Chart Widget | ThingWorx 9   Watch the following video on how to add the Bar Chart widget to a mashup and configure basic widget properties.     Button Widget | ThingWorx 9   Watch the this video to learn how to add the Button widget to a mashup and use its Clicked event to trigger data services.     Line Chart Widget | ThingWorx 9   Watch the this video to learn how to add the Line Chart widget to a mashup and bind a data source.     ReImagine Your Application UI With Collection and Custom CSS   Create compelling, modern application user interfaces in ThingWorx with the latest enhancements to our Mashup visualization platform - Collection and Custom CSS. In this webinar with IoT application designer Gabriel Bucur, we'll show how the new Collection widget makes it easy to replicate visual content in your UI for menu systems, dashboards, tables, and more.     Testing Your Edge Application   Native testing is an often-overlooked aspect of edge application development. This session shares how to perform thorough testing before you push your application into live production.     Predictive Maintenance with Thingworx 101   Adopting a predictive maintenance strategy for the first time can often feel daunting, but it doesn't have to. Learn how ThingWorx can be used to leverage edge devices and turn monitoring activity into action.     ThingWorx Mashup Pitfalls: What to Avoid and What Not to Do   Designing Mashups takes time. Moreover, expanding upon a Mashup that was built for a small-scale application can get cumbersome.     IoT Security: Keeping Devices Safe in a High Risk World   Understanding access controls can be difficult. With the built-in security features and concepts in ThingWorx, you can easily give your devices access on-demand.     Edge Connectivity in Unreliable Networks   The Store and Forward feature within ThingWorx Industrial Connectivity assures users that critical data collected at the edge won't get lost during an outage.  
View full tip
  Setup user interfaces and ways to track events   GUIDE CONCEPT   Being able to view your logs is an important part of knowing what is happening in your system. You can't keep things secure if you don't know who is doing what.   These concepts and steps will allow you to focus on development of your application while still allowing the ability to utilize the power of ThingWorx!   We will teach you how to access the system in a way you might not have done much of before.     You'll learn how to   How to design and implement meaningful user interfaces View different logs and search for data NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes   Step 1: Example and Strategy   If you’d like to skip ahead, download the completed example of the Aerospace and Defense learning path attached: AerospaceEntitiesGuide1.zip. Import the .twx files included.   In an ever-changing world, you are going to need to protect everything that is considered private. In order to do this, you need to be able to track every bit of what is happening in your system. ThingWorx does not provide an out of the box method to log when users open a Mashup window. What if this Mashup contains secure documents? Well, we can work with you on getting that logged and tracked.   Let us start working on securing our system by adding some Mashups that are simple, but we will add complexity around them. Before designing our Mashups, we will set permissions and go from there.      Step 2: Setting Mashup Permissions We will create a Mashup, but the focus will be the security of the Mashup, not the Design and UI itself. Follow the steps below to get started. In the ThingWorx Composer, click the + New at the top of the screen. Select Mashup  in the dropdown. 3, Select Responsive for the layout option. 4. Click Ok.   5. Enter a name for the Mashup Template, such as SecureMashupExample.   6. Click Save then click the Permissions tab. 7. On the Visibility tab, in the Search Organization text box, begin typing and select PTCDefenseDepartment. This allows anyone in the organization to be able to access this Mashup.    8. On the Runtime tab, in the Search Users and User Groups text box, begin typing and select Agency.IT.  9. Set all permissions to Allow (check). This allows a User Group to run services during Runtime of your application. Keep in mind, this gives permissions to all parts of the Mashup (Events, Subscriptions, Services, Parameters). 10. If you would like to be more specific, in the Search Properties, Services, or Events text box, select a service, ie GetHomeMashup. In the text box that appears below for Users and User Groups, select Agency.HumanResources.  11. On the Design Time tab, the Search Users and User Groups text box, begin typing and select Agency.IT.  12. In the Search Users and User Groups text box, begin typing and select Agency.HumanResource. 13. For Agency.IT, set the permissions to allow Read, Update, and Delete. For the Agency.HumanResource User Groups allow Read and deny Update and Delete.   You have just begun the process to securing the application from users looking to view specific secure pages. Next, let's create a simple page and show how we can log who accesses specific pages.      Step 3: Designing Tracked Mashups We will be creating a simple Mashup with the focus of showing how to add logging to a Mashup. Let's start by opening up the Mashup we just created.   Open the SecureMashupExample Mashup and click on the Design tab. Click the Layout panel in the top left and add a Bottom Container. In the Widgets panel, drag and drop a Blog Widget to the top container.   Drag and drop a Web Frame Widget to the bottom container.   Select the Blog Widget in the top container. In the Properties panel, update the Blog property to any existing or new Blog entity (there is a Blog in the provided download).    Select the Web Frame Widget in the bottom container. In the Properties panel, update the URL field to a website you trust. In this case, I'll be using https://www.ptc.com/.   Click Save and View Mashup.   When accessing this Mashup, nothing is logged. We'll be changing that in the next steps with a service that will be called and log who is using the Mashup.   In the ThingWorx Composer, click the + New at the top of the screen.   Select Thing in the dropdown.   In the name field, enter SecureServices and select GenerticThing as the Base Thing Template. Click Save and go to the Services and Alerts tab. Click the New button. Enter LogMashupAccess as the Service name.   Click the Input section and add a required String parameter named MashupName. Click Done and Add.   Add a second String parameter named Username that is required. Click Done.   Enter the below lines of code into the canvas. It will be a simple log statement for tracking. We can add a lot more to this method if we liked. logger.trace(MashupName  +  " accessed by " + Username); Click the green Save and Continue button to save your work.   Add Log Service to Mashup   We'll now need to call this logging service to see whenever a user has logged into our secure page. Of course, this is a simplified example and much more could be done here. Go back to the SecureMashupExample Mashup. In the Data panel, click the + button to add a service. Search for our new SecureServices Entity, then add the LogMashupAccess service. Ensure the Execute on Load checkbox is checked.  Click Done. Select the LogMashupAccess service. In the Data Properties panel in the lower right. In the MashupName text box, enter SecureMashupExample.   Select the User panel in the top right. Drag and drop the name field to the Username parameter. 9. Click Save.   You now have a Mashup that will log the UI being opened and the user accessing that UI whenever it is opened. Click View Mashup and go to the ScriptLog in order to test. You filter will need to be set to All or at least Trace to see the log statement.   In the next section we'll see how we can test this and do a bit more.     Step 4: Viewing and Filtering Logs   Data logging and filtering is one of your most powerful tools not only in the ThingWorx environment, but in developing solutions. The next section of this learning path will go in depth about what each of these items in a Monitoring screen does. It will also cover tricks to help your search. For now, let's look at how we can view logs and filter them to find what we need.   No.  Item Usage  1  Search Bar  Search the log for key words and phrases. 2  Filter Button  Provides a list of options to fine tune your search. This menu is very powerful. 3  Log Configurations  Select what level of logging you'd like to see. 4  Date Range  A date range filter to help limit or set your specific date options. 5  Max Row Count  The max number of rows to search for and return. The search will continue until this number is met or your other search filters have been met (ie, date range). 6   Apply/Reset Buttons  Apply the changes for your date range and max account or reset these values to their defaults. 7  Refresh/Auto Refresh Buttons Allow the log to continue based on your filters (if any) without you having to refresh. You can also refresh it on your own. 8  Log Header and List  The logs that were found based on your filters or settings. 9  Selected Log View  After selecting a log item in the list, it will be shown here.   The are some tricks to finding what you want and need faster. We dive into that in the next guide in this learning path.     Step 5: Next Steps Congratulations! You've successfully completed the Tracking Activities and Stats guide, and learned how to use the ThingWorx Platform to help track what is happening in your application.   If you wish to return to the learning path, click Utilizing ThingWorx to Secure Your Aerospace and Defense Systems   Learn More We recommend the following resources to continue your learning experience: Capability Guide Build Design Your Data Model Manage Data Model Implementation Guide Additional Resources If you have questions, issues, or need additional information, refer to: Resource Link Community Developer Community Forum Support REST API Help Center  
View full tip
Announcements