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

Community Tip - When posting, your subject should be specific and summarize your question. Here are some additional tips on asking a great question. X

IoT Tips

Sort by:
    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
  Connect to an existing database and design a connected data model.   GUIDE CONCEPT   There are times you already have your database designed and only need to integrate the ThingWorx environment.   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 create a data model around your database design and connect to that database.     YOU'LL LEARN HOW TO   How to connect an external database and created services to be used with it How to design and implement a new data model based on an external resource Using data models with database services   Note: The estimated time to complete this guide is 30 minutes.      Step 1: Examples and Strategy   If you’d like to skip ahead, download and unzip the completed example of the Aerospace and Defense learning path attached to this guide:  AerospaceEntitiesGuide1.zip.   By now, you likely know how to create a data model from scratch. You have likely already created services that work with Info Tables. What you might not have completed, is combining both a new data model, handling data in services, and connecting it all to an external database.   Our organization, PTC Defense Department, has existed for years and has an existing database setup. Developers in our organization refuse to remodel the database, so we must model the ThingWorx data model to our database schema. With ThingWorx, this is not a difficult task, but there are numerous decisions and options that we will explore in this guide.     Step 2: Database Connections   ThingWorx is based on the Java programming language and can make connections to any database that supports a Java-based connection. Dropping the JAR file for the database JDBC driver to the lib folder of Tomcat is all that is needed for connection to the ThingWorx Platform. Follow the below steps to get started creating the connection.   To establish the connection and begin working with an external database, you will need to create a Database Thing and configure the connection string and credentials. Let us start with our database connection. If you have not done so already, download the Aerospace and Defense database scripts: DatabaseApplication.zip. Use the README.txt file to create the database schema. It is based on Microsoft SQL Server, but you can configure the scripts to your database preferences.   NOTE: You will not need to connect to a database to utilize this guide as a learning utility. For your services to work, you will need to connect to a database.   1. In ThingWorx Composer, click the + New at the top-left of the screen.     2. Select Thing in the dropdown.     3. Name the Thing `DatabaseController.Facilities` and select Database as the Base Thing Template.     4.Click Save and go to the Configurations tab.   In this tab, you will enter the class name of your driver, the connection string for that database connection, and the credentials to access the database.   Keep in mind, the JDBC Driver Class Name, JDBC Connection String, and the connection Validation String values are all database type specific. For example, to connect to a SQL Server database, the below configuration can be used.   Title Description  Example   JDBC Driver Class Name  The specific class name of the driver being used for the connection.  net.sourceforge.jtds.jdbc.Driver (SQL Server) or oracle.jdbc.driver.OracleDriver (Oracle)  JDBC Connection String  The connection string to locate the database by host/port/database name.  jdbc:jtds:sqlserver://server:port/databaseName (SQL Server) or jdbc:oracle:thin:@hostname:port:databaseName (Oracle)  connectionValidationString  A simple query that should always work in a database.  SELECT GetDate() (SQL Server) or SELECT SYSDATE FROM DUAL (Oracle)   5. After entering credentials, click Save.     6. Go the Properties and Alerts tab.   The connected Property should be checked. This property informs us of the current connection to the database. The lastConnection Datetime Property should show a current timestamp. This property informs us of the last time there was a valid connection to the database. This is an easy way to confirm the connection to the database.   If you do not have a connection, work on your configurations in the Configurations tab and validate the credentials being used. If you are still having troubles, see the examples section below or use the next section for help to try a query of the database.   Help and Troubleshooting   For help finding the correct configuration for you, check out these JDBC Configuration Examples or try out this Connection String Reference for help with your connection string.   You have just established your first database connection! Now jump to the next section and let us begin to build a data model to match the database schema.   Step 3: Query Data from External Database   Now that you're connected to the database, you can begin querying the database for information and the flow of data. The queries and data shown below are based on the table scripts provided in the download.   Examples of how the ThingWorx entity should look can be seen in the SQLServerDatabaseController and OracleDatabaseController entities.   Running a Query   As you may have noticed by working in ThingWorx and developing applications, an InfoTable is often used to work with large sets of data. An InfoTable is also how data is returned from a database query. If you're expecting only 1 value in the result set, the data will be held in the first index of the InfoTable. If you're expecting rows of data coming back, expect there to be rows of information inside of the InfoTable.   Follow the steps below to set up a helper service to perform queries for the database. While other services might generate the query to be used, this helper service will be a shared execution service.   In the DatabaseController entity, go to the Services tab. Create a new service of type SQL (Query) called RunDatabaseQuery.           3. Set the Output as InfoTable, but do not set the DataShape for the InfoTable.       4. Add the following parameter: Name Base Type Required query String True       5. Add the following code to the new service:   <<query>>       6. Click Save and Continue. Your service signature should look like the below example.       You now have a service that can run queries to the database. This is also a simple method to test/troubleshoot the database connection or a quick query.   Run your service with a simple query. You might notice that no matter the fields in the result set, the InfoTable will match it based on field type and field name.   There are two ways you can go from here. You can either query the database using services that call this service, or you can create more SQL command services that query the database directly. Let's go over each method next, starting with a service to call our helper.   In the Services tab of the DatabaseController entity, create a new service of type JavaScript. Name the service JavaScriptQuery_PersonsTable. Set the Output as InfoTable, but do not set the DataShape for the InfoTable. Add the following code to your new service: try { var query = "SELECT * FROM Persons"; logger.debug("DatabaseController.JavaScriptQuery_PersonsTable(): Query - " + query); var result = me.RunDatabaseQuery({query:query}); } catch(error) { logger.error("DatabaseController.JavaScriptQuery_PersonsTable(): Error - " + error.message); }       5. Click Save and Continue.   Any parameter, especially those that were entered by users, that is being passed into an SQL Statement using the Database Connectors should be fully validated and sanitized before executing the statement! Failure to do so could result in the service becoming an SQL Injection vector.   This is a simple way to query the database since much of your development inside of ThingWorx was already based in JavaScript.   Now, let's utilize the second method to create a query directly to the database. You can use open and close brackets to create parameters for your query. You can also use <> as a method to mark a value that will need to be replaced. As you build your query, use [[Parameter Name]] for parameters/variables substitution and <> for string substitution.   In the Services tab of the DatabaseController entity, create a new service of type JavaScript. Name the service SQLQuery_GetPersonByEmail. Ensure the Output is InfoTable. Add the following code to your new service: SELECT * FROM Persons WHERE person_email = [[email]];       5. Add the following parameter:   Name Base Type Required email String True         6. Click Save and Continue.   An example of using the string replacement is as follows: DELETE FROM <> WHERE (FieldName = '[[MatchName]]'); DELETE FROM << TableName >> WHERE ( FieldName = [[MatchNumber]]);       Click here to view Part 2 of this guide.
View full tip
  Step 3: Create Validation and Status   With our MyFunctionsMashup Mashup open, let's add a Validation. A Validation is similar to an Expression, except you have the added capability of triggering Events based on a True or False outcome of your validation. We will use the Validation to check and confirm the Text Field we created only has the values we added in our Functions. Let's also add two Status Message Functions that will show whether or not a user has added any text outside of what we want.   Open the MyFunctionsMashup Mashup to the Design tab. Click the green + button in the Functions area.    In the New Function modal, select Validator.   Set the Name to isDataClean.   Click Next.  Click Add Parameter. Set the Name to text and ensure the Base Type is STRING.   Add the following code to the Expression are: if(text === "NO") { result = true; } else if(text === "YES") { result = true; } else { let array = text.split("YES").join(""); array = array.split(",").join(""); let count = array.trim().length; if(count) { result = false; } else { result = true; } }   9. Click Done.   We have our Validator in place, now we need our two Status Message Functions. Why two? You can setup one Status Message to perform the task, but for this case, we're keeping things simple.   Click the + button in the Functions area. Select Status Message in the dropdown.    Set the Name to GoodInputProvided.   Click Next. Ensure Message Type is Info. In the Message field, enter Text is all good!.   Click Done. Let's create another Status Message Function. Set the Name to BadnputProvided.   Click Next. Change Message Type to Error. In the Message field, enter Text is BAD!.   Click Done.   We now have two Status Message Functions and a Validator to help with checking our text data. Let's connect everything together. This time, let's use the Bind button.   Expand the Validator section in the Functions tab. Click the Bind (arrows) button on the isDataClean Validator. This window will help us configure connections a bit easier.    Click the down arrow by the True Event. Click Add Trigger Service.   Click Functions. Check the checkbox by GoodInputProvided.   Click Next. Click the down arrow by the False Event. Click Add Trigger Service.   Click Functions. Check the checkbox by BadInputProvided.   Click Next. You should currently have the following setup:    Let's add in our connections to the Text Field and when we'll run this Validation.    Click the down arrow by the text Property.   Click Add Source. With the Widgets tab selected, scroll down and select the Text Property of our Text Field.   Click Next. Click the down arrow by Evaluate Service. Select Add Event Trigger.   With the Widgets tab selected, scroll down and select the Clicked Property of our Button.   Click Next. You should currently have the following setup:   Click Done. Click Save and view your updated Mashup.   Your Validator is complete. You now have a way to tell when a user has inputed their own text into the text box. To try things out, add some crazy characters, hit the button, and see what happens. You might notice that you have your Expressions running at the same time as your Validator. Switch up the bindings to get it to run the way you want it to.     Step 4: Create Confirmation Modal   With our MyFunctionsMashup Mashup open, let's add a Confirmation Function. A Confirmation Function provides a quick modal that will give users a method to confirm actions or events before they take place. If you've ever almost deleted a production database (don't judge me!), then you know how handy a confirmation screen can be. Let's add a button that will trigger a confirmation as to whether we would like to run the Validator we created in the last section.   Open the MyFunctionsMashup Mashup to the Design tab. Click the + button in the Functions panel. Select Confirmation in the dropdown.   Set the Name to confirmDataValidation. Click Next.   Set the Title Text to Confirm Data Validation?. Set the Message Text to Would you like to perform a data validation?.   Set the Cancel Button Label to No Thanks!. Scroll down and set the Action Button Label to Yes Sir!.   Click Done. Click the Widgets tab in the top left. Filter for and select a Button Widget.   Drag and drop a Button Widget onto the Canvas.   With the new Button selected, click the down arrow that appears on the Button. Drag and drop the Clicked Event of the Button to the OpenConfirmation Service of our Confirmation Function.     We now have our Confirmation Function and a Button that will open the Confirmation when clicked. Let's add the final step by connecting the Confirmation to our Validation Function.   Click the Bind (arrows) button for our isDataClean Validator.   Click the down arrow by the Evaluate Service. Select Add Event Trigger.   Click the Functions tab. Select the ActionClick Event of our Confirmation Function.   Click Next. Click Done. Click Save for our Mashup.   We now have a way to independently validate that the text in our text box does not contain random values added by the user. View the Mashup and test things out by clicking on the second button and adding some crazy characters to our text box.       Step 5: Create Navigation   Thus far, we have been sticking to one Mashup. Let's venture out a bit by showing a different Mashup. Inside of our MyFunctionsMashup Mashup, we will add a Navigation Function. This will allow us to go to or just show a different UI based on some kind of user input or event. For our example, when a user clicks No Thanks! in our Confirmation Function, let's send them to a different Mashup.   Follow the steps to create a Navigation Function, a destination Mashup, and tie the two together.    Create Destination Mashup Navigate to Browse > Visualization > Mashups.   Click + New. Keep the defaults and click OK. In the Name field, type MyNavigationDestination.   Click Save. Click the Design tab at the top to open the Mashup canvas. Click the Widgets tab.   Filter and search for the word Label. Drag and drop a Label Widget to the Mashup canvas. If you like, enlarge the Label sizing.    In the Label Widget Properties section, scroll down to the LabelType Property.       Click the dropdown and select Large Header.   In the LabelText Property field, type MY DESTINATION UI SCREEN. Click Save. You have now created a simple UI that we will go to when we click our navigation button. Next, we'll tie together our navigation button and our freshly created Mashup.   Create Navigation Function Reopen the MyFunctionsMashup Mashup to the Design tab. Click the + button in the Functions panel. Select Navigation in the dropdown.   Set the Name to travelToDestination.   Click Next. Set the Target Window Type to ModalPopup. Set the Pop-up Title to New Popup Here.   Set the Pop-up Width to 400. Set the Pop-up Height to 400.   Click the + button at Target Mashup. Type MyNavigationDestination into the search bar. Select the MyNavigationDestination Mashup when it appears.   Click Done. Select the Bind (arrows) button for our new travelToDestination Navigation Function.   Click the down arrow next to Navigate Service. Click Add Event Trigger.   Click the Functions tab. Select the CancelClick Event of our confirmDataValidation Confirmation Function.   Click Done. Click Save for the Mashup.   We now have a modal that will appear after we click the No Thanks! button in our Confirmation Function. View the Mashup and try out what you've done by clicking the bottom button, then clicking No Thanks!     Click here to view Part 3 of this guide.  
View full tip
    Step 7: Add Grid   It might also be helpful to display the data you've used to build the ThingWorx Analytics model.   In the future, this might be split out into an entirely separate page/Mashup that is exclusively devoted to backend model creation, but that would be beyond the scope of this guide.   For now, we'll simply display that collected data via the Grid Widget      1. On the EEFV_Mashup, drag-and-drop a Grid Advanced Widget onto the bottom-left Canvas section..     2. On the top-right Data tab, click the green </> button beside Things_EdgeThing. Note that this will open the Add Data pop-up, but with EdgeThing pre-selected.   3. In the Services Filter field, type getproperties.   4. Click the right-arrow beside GetProperties to add it to Selected Services on the right.   5. Check Execute on Load.     6. Click Done.   7. Under the Data tab, expand GetProperties to reveal the options.     8. Drag-and-drop Things_EdgeThing > GetProperties > infoTableProperty onto the Grid Advanced Widget.     9. On the Select Binding Target pop-up, click Data.     10. Click Save.   11. Click View Mashup.         Step 8: Add Controls   Throughout this Learning Path, it has been recommended that you stop Analysis Events when not actively using their functionality.   However, this requires going into the backend of ThingWorx Analytics to disable the event, which is not ideal.   Instead, let's enable or disable the Analysis Event from inside the Mashup by adding some Button Widgets to directly interface the Analytics backend for us.       1. Click the bottom-right Canvas section to select it.         2. In Mashup Builder top-left, click the Layout tab.         3. Under Positioning, click the Static radio-button.         4. Click the Widgets tab.       5. Drag-and-drop a Button Widget onto the bottom-right section.         6. Drag-and-drop another Button Widget onto the bottom-right section.       7. Drag-and-drop a Text Field Widget onto the bottom-right section.       8. Click Save.       Bring in More Data   Now that we have Buttons to trigger enable/disable, as well as a Text Field to display information, we now need to bring in some additional Mashup Data Services to interact with the ThingWorx Analytics backend.       1. Click the green + button at the top of the Data tab.       2. In the Entity Filter field, search for and  select TW.AnalysisServices.EventManagementServicesAPI.       3. In the Services Filter field, search for and add QueryAnalysisEvents by clicking the right arrow.       4. Check Execute on Load.         5. In Services Filter, search for and select EnableAnalysisEvent by clicking the right arrow. Note that you should NOT check "Execute on Load", as we'll trigger this Service only when the Button is clicked.     6. In Services Filter, search for and select DisableAnalysisEvent by clicking the right arrow. Likewise, do NOT check "Execute on Load" here either.       7. Click Done.         8. Click Save.     Display Event Key   To enable or disable Analytics Events, we need to know the eventId, which is returned by QueryAnalysisEvent Service as the parameter labeled key.   We'll bind that to the Text Field Widget for later usage in enabling/disabling.        1. Change the top-button's Label Property to Enable Analytics Event.       2. Change the bottom-button's Label Property to Disable Analytics Event.         3. Under the Data tab, expand QueryAnalysisEvents > Returned Data > All Data to reveal the options. .       4. Drag-and-drop QueryAnalysisEvents > Returned Data > All Data > key to the TextField Widget.         5. On the Select Binding Target pop-up, click Text.         6. Click Save.     Enable/Disable Analytics Events   Now that we know the key/eventId, we can call the EnableAnalysisEvent and DisableAnalysisEvent services.       1. Under the Data tab, expand EnableAnalysisEvent > Parameters to reveal eventId.       2. Click the Text Field Widget to select it, and then click the top-left drop down to reveal the options.         3. Drag-and-drop the Text Field's Text Property onto EnableAnalysisEvent > Parameters > eventId.         4. Repeat steps 1-3 for DisableAnalysisEvent.         5. Click the Enable Analytics Event Button Widget to select it, then click the top-left to reveal the drop down option .       6. Drag-and-drop the Clicked Event onto the EnableAnalysisEvent Service under the Data tab.         7. Repeat steps 5-6 for DisableAnalysisEvent, using the other Button Widget.         8. Click Save     Step 9: View Mashup   Throughout this guide, we've added various additional functionality to our MVP Mashup. At this point, you could continue to update the Mashup as you see fit.   For instance, you could change the background color of the top-left section to better match the header. Or you could further modify the original Mashup shown in the Contained Mashup Widget so that it better fits in the allowed space. You could add another Label Widget to the Header section to also display the company's motto / tag-line.   Regardless, when you are done with modifications, Save and click View Mashup.     Note that you can left-click-and-drag on the Time Series Chart to select particular time ranges. Or you could add a Time Selector Widget to the bottom-right section to control it there.   Similarly, you could add controls for the Grid Widget to only show the Identifier ranges in which you were interested.   Or you could split out the Model-creation values to a completely separate Mashup as previously discussed.   The extent to which you develop your Mashup is entirely up to you.        Step 10: Next Steps   Congratulations. You've completed the Enhanced Engine Failure Visualization guide. In this guide, you learned how to:   Create a Mashup with a Header Divide your Mashup into Sub-sections Use a Contained Mashup to reuse development Store historical data in a Value Steam Display historical data in a Line Chart Show spreadsheet data via a Grid Advanced Widget Tie Mashup controls into the ThingWorx backend   This is the last guide in the Vehicle Predictive Pre-Failure Detection with ThingWorx Platform learning path.   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
  Utilize the C SDK to build an app that creates a secure connection to ThingWorx with low level device access.   Guide Concept   This project will cover using the ThingWorx C SDK to develop applications for the purpose of secure and low level 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. Basic concepts of the C Edge SDK How to create an application that can communicate with other devices   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL parts of this guide is 60 minutes       Step 1: Completed Examples   Download the completed files attached to this tutorial: C_SDK.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 flushed out application. With the C SDK, you can connect to whatever device you have at a level most programming languages wouldn't be able to. Now think of your secure system, your fighter jet, or even you communication devices. All these systems and levels need to have a way to secure transfer data and the C SDK is how we do it.   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, download the attached C compiler: C-SDK-2-2-12-1052.zip.    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 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, which provides examples of how to utilize the C SDK. Open a terminal, go to your workspace, and create a new project. After you've created this project in your workspace, import the entire C SDK downloaded from the PTC Support site for ease of use (mainly the src folder and the CMakeList.txt file). 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-37dc6dd34618" 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.   If you have not downloaded and installed CMake, do it now at the CMake website. NOTE: CMake comes as a command line and a GUI application. The steps in this guide use the command line version only. Inside the specific example folder you would like to run, ie SteamSensor. Create a directory to build in, for this example call it cmake. mkdir cmake cd cmake 4. Run the CMake command listed below. This assumes CMake is already on your PATH. cmake -G "Visual Studio 15 2012" .. 5. CMake has now produced a set of project files which should be compatible with your development environment.  Operating System    Command                                        Notes Unix command-> 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.   6. Once your build completes you will find the build products in the cmake directory. 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.       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   3. 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"   4. 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. 5. Click Save and close the file. 6. 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   7. Change to the newly created bin directory.  Operating System              Command Linux/Ubuntu cd bin Mac cd bin Windows cd bin   8. 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 ..   9. 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 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 2 of this guide.      
View full tip
  Use Subsystems to retrieve User/Thing-count and License-expiration information   Guide Concept   In this guide, you'll learn how a Foundation Administrator can access important license-accounting Subsystems.    In particular, we'll look at the User Management and Licensing Subsystems, and how you can use them to ensure that you're not getting close to running out of Users, Things, or your time-to-expiration.    We'll also explore how you can import a new license_capability_response.bin file when your original license is running low on time.      You'll learn 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   NOTE: The estimated time to complete ALL parts of this guide is 30 minutes     Step 1: Introduction   ThingWorx Foundation uses a licensing system based around a file named license_capability_response.bin.  However, if you're using the downloadable installer, then it's possible that you've never even touched this part of the system before.   Besides doing the initial install, you'll also have to check to see that your license has enough Users, Things, and time left before expiration. You need to ensure that a new license is acquired and properly replaced beforehand... or else your Foundation installation may become unusable.    Therefore, this guide will run you through how to access that information, as well as how to update to a new license_capability_response.bin file when the time is right.      Step 2: Get User Count   The first item we'll investigate is checking on our number of Foundation Users.    When first developing an IoT application, low User counts are typically the norm. Only your team really needs access to Foundation itself, so having only a few Users more than your R&D-team-size is possibly going to be sufficient.    And, if your application is something along the lines of factory-monitoring, then it's possible that your User counts, even when deployed, are going to continue to stay relatively low.    However, many IoT applications involve a tremendous number of Users, as your end-customers will generate a Foundation User whenever they sign up for your application. Think something along the lines of a ride-sharing app, or even a Smart Cities play... either of those can result in thousands (if not tens-of-thousands) of Users.    As such, a Foundation system administrator will need to keep a tight track on the User counts to ensure, whenever you're approaching your upper threshold, that enough warning is given to provide time to receive and install a new license_capability_response.bin with a larger User count.    Navigate to Foundation Composer's Browse > All.   On the left-side Navigation, scroll down until you see the System section. Note that you will likely be unable to even see the System section unless you are an Administration-level User.   Click Subsystems.   Click UserManagementSubsystem.   At the top, click Services.   Scroll down and find the built-in GetUserCount Service.   On the line for GetUserCount, click the "play" icon for Execute Service.   At the bottom-right of the pop-up, click Execute.   Click Done to close the pop-up. The return value from GetUserCount is one way to reveal how many current Users are provisioned for your Foundation system.    Moving forward, we'll explore yet another way, while also looking into our Thing counts.    In particular, you might find that the GetUserCount value doesn't completely match due to some internal system accounts. These system accounts are not counted against your license, however, and may need to be accounted for when using the GetUserCount Service.        Step 3: Get Current License Info   While GetUserCounts can be helpful for getting the current amount of provisioned Users, it does nothing to compare that count to the total allowed by the license.    Instead, we'll make use of a different Subsystem, i.e. the LicensingSubsystem.    Return to Browse > System > Subsystems.   Click LicensingSubsystem.   At the top, click Services.   Scroll down until you find GetCurrentLicenseInfo.   On the GetCurrentLicenseInfo line, click the "play" icon for Execute Service.   On the bottom-right of the pop-up, click Execute.   When you're done analyzing the counts, click Done to close the pop-up.   The first thing to notice is that the InUseFeatureCount for twx_named_user possibly does not match the return of GetUserCount. As already mentioned, this is because of system accounts that are not counted against your license.    For example, for a fresh installation, the GetUserCount may return 4, while InUseFeatureCount returns 2. The 2-count is more accurate, as it is used versus your total license-amount. However, GetCurrentLicenseInfo is less useful for doing a simple comparison between a stored "last user amount" vs "current user amount".    The solution is simple. Compare the return of GetUserCount versus the return of GetCurrentLicenseInfo to determine the true total. In this case, the number of system accounts is 2, so some "GetUserCount - 2" custom-Service could be very helpful.   In addition, GetCurrentLicenseInfo returns the very important twx_things value, i.e. how many Thing Entities have been created in the system. This is typically another hard limit in your license, and needs to be watched over.    Finally, the DaysRemaining column shows how long you have before your license becomes inactive. This is something which needs to be constantly monitored to ensure that your Foundation system as a whole is still running!   Next, we'll explore making a Mashup to reference these built-in Services in a more comfortable environment which auto-updates and can be used as, effectively, a Foundation system dashboard.     Step 4: Create Dashboard Mashup   While the User Management and Licensing Subsystems can be used as previously described to determine relevant admin information, traversing through the Foundation backend can be tedious.    To make User, Thing, and License Expiration Date counts easier to monitor, we'll now create a "dashboard" which automatically pulls this information into a convenient Mashup.    Navigate to Browse > Visualization > Mashups.   Click + New.    Leave the defaults and click OK.   In the Name field, type Licensing_Mashup.   If Project is not set, search for and select PTCDefaultProject. Click Save. Click Design.   Set Layout   Now that we have a new Mashup, we'll start adding the items we'll need to display information from the Subsystems.    First, we'll change the Layout.   In the top-left, ensure that the Layout tab is active.   Click Add Top.   Ensure the new top section is selected, and set Positioning to Static.   Scroll down in the Layout tab, and set Container Size to Fixed Size.   In the new Height field, type 100, and then hit your keyboard's Tab key to lock-in your change. Note that the px will be automatically added after hitting the Tab key.   At the top, click Save.   Add Widgets   Now that we have the Layout we want, we can add Widgets to display data coming from the backend.   In the top-left, click the Widgets tab.   Drag-and-drop a Label Widget onto the top section.   With the Label still selected, in the bottom-left Properties section, change LabelText to User Count, and hit Tab.   Drag-and-drop a Text Field Widget, also in the top section, and below the Label.   In the top-left Widgets tab, change Category to Legacy. Drag-and-drop an Auto Refresh Widget in the top section as well.    In the top-left Widgets tab, change Category back to Standard. Drag-and-drop a Grid Advanced Widget onto the Bottom section.   At the top, click Save.   Click here to view Part 2 of this guide.
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
  Step 6: Building the Data Model   You can build your data model using different methods. You can build your data model where the Data Shapes match with your tables, but what you'll realize over time is that you will often need custom Data Shapes. When you query for data, you will often need data from differing tables to be in one result set. Because of this, I suggest against making your data model based on the tables. You can start the basis for your model with the tables in mind, but know that this won't be the basis for long.   Create Data Shapes   Let's start by setting up two queries and the Data Shapes to match. The first query will be to find the list of classes a student is assigned to and query will be completed here. The second query will be to find all student in an active class and we'll ask you to create it based on how we did the first one.   1. In the ThingWorx Composer, click the + New button in the top left.    2. In the dropdown list, click Data Shapes.   3. Name the Data Shape DataShape.StudentCourses   4. Add the set of fields below. You may notice, we included information from the Person table that we might already have. This is perfectly fine based on how much data you expect to come back. This will allow you to reuse this database for other purposes later where the person information might change. This can be very beneficial when you're calling a service with this Data Shape (or InfoTable based on this Data Shape). Allowing you to keep the input simple.    Name Base Type  Additional Info   id  STRING Primary Key   person_key  STRING  N/A  person_name_first  STRING  N/A  person_name_last  STRING  N/A  course_key  STRING  N/A  course_name  STRING  N/A  course_professor  STRING  N/A   Let's add in our database query and use our new Data Shape.    1. Open the DatabaseController.Facilities entity and go to the Services tab. If you have not done so as yet, add the configuration information to allow your queries to connect to a database. 2. Create a new service of type SQL (Query) called GetStudentEnrollment. 3. Click Save and Continue to save your changes.   4. Add a parameter to the service title email. It will have a String base type and be required. 5. Add the following query to the canvas.         SELECT person_key, person_name_first, person_name_last, course_key, course_name, course_professor FROM Person person INNER JOIN PersonCourses pc ON person.person_key = pc.person_key INNER JOIN Courses courses ON courses.course_key = pc.course_key WHERE person.person_email = [[email]]​           6. For the output of the service, InfoTable should be there by default. If not, switch the output to be an InfoTable. For the Data Shape, set it to the Data Shape we just created, DataShape.StudentCourses.   You now have a database where you can run your queries and use the responses to bind to Widgets in Mashups.    We have our database connection and a data model setup to handle our current queries. This might be where you begin to question if you would like to add Data Tables. This is more of a design choice. You might want to keep datasets in a Data Table for quick access or separation. Nevertheless, if you already have you database, you won't need many (if any) Data Tables.     Step 7: Next Steps   Congratulations! You've successfully completed the guide for Connecting to an External Database, and learned how to use the ThingWorx Platform to connect to database, query for data, and write new data.   The next guide in the Utilizing ThingWorx to Secure Your Aerospace and Defense Systems learning path is Low Level Device Connection.   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Design Your Data Model Build Configure Permissions   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum
View full tip
  Connect a Raspberry Pi to ThingWorx using the Edge MicroServer (EMS).   GUIDE CONCEPT   This project will utilize the Edge MicroServer (EMS) to connect ThingWorx Foundation to a Raspberry Pi.   YOU'LL LEARN HOW TO   Set up Raspberry Pi Install, configure, and launch the Edge MicroServer (EMS) Connect a remote device to ThingWorx Foundation   NOTE:  The estimated time to complete all parts of this guide is 60 minutes.     Step 1: Introduction   A Raspberry Pi is a small, single-board computer that utilizes an ARM processor and typically runs a variant of Linux.   Due to its small size, relatively affordable cost, and ability to run a full operating system, the Pi is a near-ideal device to utilize as a Proof-of-Concept (PoC) IoT Edge device.   In addition, there is a version of the ThingWorx Edge MicroServer (EMS) built to work on ARM processors. Therefore, this guide will explore getting the EMS running on a Raspberry Pi to connect to ThingWorx Foundation.       As stated in the Overview, you may purchase a Pi directly from the Raspberry Pi web site or from a distribution partner such as Digi-Key or RS.   You will also need an SD card (8+GB... 16+GB recommended) with the Raspbian operating system installed... though this guide will instruct you on installing the Raspbian OS on a microsdhc flash card if you prefer to purchase an SD card separately.   You may alternately wish to purchase a "Pi Canakit". Canakits, depending on the version, typically include a Pi, SD card with a version of Raspbian pre-installed, and various other items like sensors, a case, an HDMI cable, and other accessories.   To make this guide as straight-forward as possible, we'll assume a monitor, USB keyboard, USB mouse, and WiFi connectivity to interact with the Pi.   Note that the Pi has an HDMI port, so you may also need an HDMI-to-DVI convertor or similar if your monitor doesn't natively support HDMI.     Step 2: Format MicroSDHC Card   The microSDHC flash card which the Pi accepts may (or may not) come pre-installed with the Raspbian OS. If Raspbian is pre-installed and working, you may skip this step.   However, these flash cards are susceptible to corruption, especially if proper static-control guards are not followed or if the Pi is powered-down without going through a proper shutdown procedure.   As such, the steps immediately below will assume that you are installing (or re-installing) Raspbian on your microSDHC card.   Depending on your PC's ports, you may also require a microSDHC adapter to insert the flash card into your computer.   Locate your microSDHC card. Remember that 8+GB is mandatory, but 16+GB is recommended to ensure that the Pi has enough swap-space.   Locate your flash card adapter. Note that you may have a different type of adapter. Simply ensure that your PC can recognize the microSDHC card.   Insert the microSDHC card into the adapter.     Insert the adapter-plus-microsdhc card into your PC.     Assuming a Windows PC and either a pre-installed or corrupted flash card, you will receive a pop-up stating that it needs to be formatted prior to use; click Format disk.   On the following Format SDHC Card pop-up, click Start.   On the following Format Confirmation pop-up, click OK.     On the following Format Complete pop-up, click OK.   On the previous Format pop-up which is still open, click Close.   You now have a formatted microSDHC card which Windows can recognize.       Step 3: Flash MicroSDHC Card   Now that the flash card is accessible to Windows, you want to install the Raspbian OS on it.   Once again, this step assumes that you are installing (or re-installing) the Raspbian OS.   If your microSDHC card came pre-installed with Raspbian, then you may skip this step.   Download the Raspbian OS .zip file. Navigate to the download location and locate the Raspbian .zip file.   3. Right-click on the file and select Extract All....   4. On the Extract Pop-up, click Extract.   5. Download the balenaEtcher "flasher" software. 6. Navigate to the download location and locate the balenaEtcher .exe file.   7. Double-click on the balenaEtcher .exe to begin the installation process.   8. On the balenaEtcher installer pop-up, click I Agree. After the installation completes, balenaEtcher will automatically open.   9. Click Select image and navigate to the previously-extracted Raspbian OS .img file.   10. Select the .img file and click Open. Assuming the only microSDHC card currently inserted into your PC is the one for the Pi, then the SD SCSI Disk Device will be pre-selected; otherwise, choose the correct flash disk.   11. Click Flash!. Accept allowing the etcher to make changes to your computer.   12. Wait for balenaEtcher to complete the flashing process; this may take ~5-10 minutes.   13. Remove the microSDHC card and adapter from your PC.     Click here to view Part 2 of this guide.
View full tip
  Step 5: Import Extension   Now that we have a valid dataset, we want to export it as a .csv file, which can be imported into ThingWorx Analytics in a future guide to generate an analytical model.   An easy way to do this is with the CSV Parser Extension, which you’ll now import.       1. Download the CSV Parser Extension from our third party provider IQNOX.   Note:  An account is required but the download is free.     2. At the bottom-left, click Import/Export.       3. On the drop-down, click Import.       4. For Import Option, select Extension.       5. Click Browse and navigate to the extension you downloaded above.       6. Click Open.       7. Click Import.       8. Click Close.       9. On the Refresh Composer? pop-up, click Yes.      Step 6: Create File Repository   ThingWorx Foundation uses File Repositories to read and write files from disk (including .csv files created by the CSV Parser Extension).   In this step, we’ll create a File Repository Entity.       1. Return to Browse > All.       2. Click MODELING > Things.       3. Click + New.       4. In the Name field, type ESDS_File_Repository.       5. If Project is not already set, search for and select PTCDefaultProject.       6. In the Base Thing Template field, search for and select FileRepository.      7. At the top, click Save.        Step 7: Create .csv Export Service   We have imported an Extension which gives us tools to manipulate .csv files. We have created a File Repository to which the export can save the file. We'll now make use of some of this new functionality.    We’ll do so by creating a Service which calls built-in functions of the CSV Parser Extension.       1. Return to EdgeThing.       2. Click Services.       3. Click + Add.       4. On the drop-down, select Local (JavaScript).       5. In the Name field, type exportCSVservice.       6. In the blank JavaScript field, copy-and-paste the following code:           var sFile = "vibrationCSVfile.csv"; var paramsCSV = { path: sFile, data: me.infoTableProperty, fileRepository: "ESDS_File_Repository", withHeader: true }; Resources["CSVParserFunctions"].WriteCSVFile(paramsCSV);               7. Click Save and Continue. Note that you should NOT click the top Save button, as that will erase your Service.         Step 8: Export the Engine Data   We now have all the tools in place to export the infoTableProperty as a .csv file to our new File Repository.   All that’s left is to call the appropriate functions.       1. Ensure that you’re still on the Services tab of EdgeThing, and have the exportCSVservice open.       2. At the bottom, click Execute.       3. Return to ESDS_File_Repository.       4. Click Services.       5. Scroll down and find the GetFileListingsWithLinks Service.       6. Click the “Play” icon for Execute service.       7. At the bottom-right, click Execute.       8. On the right, click Thingworx/FileRepositories/ESDS_File_Repository/vibrationCSVfile.csv.     9. The .csv export of the vibration data will now be in your local folder to which your browser saves downloads.       Step 9: Next Steps   Congratulations! You've completed the Engine Simulator Data Storage guide, and learned how to:   Create a Timer Subscribe to a Timer to Trigger a Service Generate Mass Amounts of Test Data Import the CSV Parser Extension Create a File Repository Export the Test Data as a Comma-Seperated Values (.csv) file Download from a File Repository   The next guide in the Vehicle Predictive Pre-Failure Detection with ThingWorx Platform learning path is Build an Engine Analytical Model   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Analyze Build a Predictive Analytics 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 Analytics Builder Help Center
View full tip
    Step 4: Create Thing   Now that we have a Data Shape to format the combination of data coming from the various sub-systems, we can now instantiate a Thing with an Info Table Property to hold all of said data.   Click Browse > Modeling > Things.   Click + New. In the Name field, type MDSD_Thing. If Project is not already set, search for and select PTCDefaultProject. In the Base Thing Template field, search for and select Generic Thing.   At the top, click Save.   Add Info Table Property   We now have a Thing to aggregate the MRI sub-system information, but we still need a Property to perform the actual storage.   We'll use an Info Table Property for this, with the columns of the Info Table formatted by the Data Shape we created in the previous step.   At the top, click Properties and Alerts.   Click + Add.   On the right in the Name field, type MDSD_InfoTable_Property. Change the Base Type to INFOTABLE. In the Data Shape field, search for and select MDSD_DataShape.   Check the box for Persistent.   At the top-right, click the "Check" button for Done. At the top, click Save.     Step 5: Create Service   Now that we have a Thing with an Info Table Property to store our aggregated data from multiple MRI sub-systems, we need to develop a Service which will grab said data and propagate that information into the Info Table Property.   At the top of MDSD_Thing, click Services.   Click + Add.   Under Service Info in the Name field, type MDSD_Aggregation_Service.     Access to MRI Sub-systems   We now need to access the various sub-systems of the MRI that are already talking to ThingWorx Foundation.   Once again, we'll only be doing so for two sub-systems in this MVP example. But the general premise will extend to as many remote devices as is necessary.   You will simply add more references as additional sub-systems are needed.   In the Javascript code window, copy-and-paste in var embedded_properties = Things["MDSD_Embedded_Thing"].GetPropertyValues(); This provides a reference to the embedded microcontroller's Properties. All Things are accessible in Foundation via the "Things" array, and you simply need to provide the Thing-name to index into the array; this functions similarly to a "global" variable, so that any Thing can reference any other Thing. The built-in GetPropertyValues Service simply returns the values of all Properties of the Thing being referenced. In the Javascript code window, copy-and-paste in var pc_properties = Things["MDSD_PC_Thing"].GetPropertyValues(); This provides a reference to the PC's Properties.     Add Values to Info Table   Now that we have references to the sub-systems, we'll add their individual Property values to each field of the Info Table Property.   We'll do this via the built-in AddRow() Service.   To begin an AddRow Service call, copy-and-paste me.MDSD_InfoTable_Property.AddRow({ The me reference is MDSD_Thing, since we're inside said Entity. The MDSD_InfoTable_Property is the Property we added in this guide's previous step. The built-in AddRow Service will add each following Property value to a field of the Info Table formatted by the previously-created Data Shape.   Copy-and-paste Coolant_Percent:embedded_properties.Coolant_Percent, This stores the embedded microcontroller's "Coolant Percent" in the first field of a row of the aggregated Info Table.   Copy-and-paste Field_Strength:embedded_properties.Field_Strength, Likewise, this references the second Property of the embedded microcontroller to store in the second field of the Info Table.   Copy-and-paste Magnet_Temperature:embedded_properties.Magnet_Temperature,   Now that we have all the embedded microcontroller's values, copy-and-paste the following lines for the PC's values: Number_of_Scans:pc_properties.Number_of_Scans,SSD_Space_Open:pc_properties.SSD_Space_Open, Unused_RAM:pc_properties.Unused_RAM,   We also want to record the Timestamp (via the built-in Date Service) when these entries were added; copy-and-paste Timestamp:Date.now()   Finally, close off the AddRow Service with some braces, i.e. copy-and-paste });   Review the entire Service in Foundation and ensure that it matches the Javascript code below. var embedded_properties = Things["MDSD_Embedded_Thing"].GetPropertyValues(); var pc_properties = Things["MDSD_PC_Thing"].GetPropertyValues();me.MDSD_InfoTable_Property.AddRow({ Coolant_Percent:embedded_properties.Coolant_Percent, Field_Strength:embedded_properties.Field_Strength, Magnet_Temperature:embedded_properties.Magnet_Temperature, Number_of_Scans:pc_properties.Number_of_Scans, SSD_Space_Open:pc_properties.SSD_Space_Open, Unused_RAM:pc_properties.Unused_RAM, Timestamp:Date.now() }); For the MDSD_Aggregation_Service, click Done. Click Save.   Test Service   Before going further, we should test the Service to ensure that it is correctly adding entries to the aggregate Info Table Property.   On the MDSD_Aggregation_Service row, under the Execute column, click the Play icon.   At the bottom-right of the Execute Service pop-up, click Execute.   Click Done, and return to Properties and Alerts. Notice under the Value column that the Info Table Property now has an entry.   Under the Value column, click the Pencil icon for Edit.   Review the values and confirm that every field has a valid entry. Note that your values will differ from those in the picture due to the random nature of the simulator. On the pop-up, click Cancel. At the top, click Save.     Step 6: Create Mashup   Now that we have a Thing that has logically aggregated the infomation into a single Info Table Property (and a Service to carry out said aggregation), we can start to visualize the data with a Mashup.   For more information on Mashups, reference the Create Your Application UI guide.   Click Browse > Visualization > Mashups.   Click + New.   On the New Mashup Pop-up, leave the defaults, and click OK. In the Name field, type MDSD_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 Layout tab.   For Positioning, select the Static radio-button.   At the top-left, click the Widgets tab. At the top, click Save.   Widgets   We now have a "Static Positioning" Mashup, which will let us drag-and-drop Widgets without them auto-expanding to fill the entire space. This will alow us to have multiple Widgets without worrying about sub-dividing the Mashup.   In particular, we're interested in the Grid Widget to display our aggregated data, as well as a Button Widget to call the Service to perform the aggregation.   On the left in the Filter Widgets field, type grid.   Drag-and-drop a Grid Advanced Widget onto the central Canvas area.   In the Filter Widgets field, type button.   Drag-and-drop a Button Widget onto the central Canvas area.   Re-size (by clicking-and-stretching) and move the two Widgets such that they look roughly like the picture below.   Click the Button Widget to select it. In the Filter Properties field of the bottom-left Properties section, type label.   In the Label field, type Retrieve MRI Statistics, and then hit the Tab keyboard key to lock in the change.   At the top, click Save.     Click here to view Part 3 of this guide.
View full tip
  Step 5: Contained Mashup   Our Minimum Viable Product (MVP) Mashup which we created in the last guide did have valid information.   Being able to display the inputs coming from the engine, as well as the analytical results coming from ThingWorx Analytics, are certainly items we don’t want to lose in this new, more complete Mashup.   Rather than recreating that work from scratch, we’ll simply include that previous Mashup in one of our sub-section via the Contained Mashup Widget.       1. Click on the top-left section to select it, and ensure that you’re on the Widgets tab in the top-left.       2. Drag-and-drop a Contained Mashup Widget onto the top-left section.       3. With the Contained Mashup Widget selected, return to the Properties tab in the bottom-left.       4. Scroll down and locate the Name Property.       5. Search for and select EFPG_Mashup       6. Click Save.     Add Column Labels   The original Mashup we created (and have now embedded in the new one) had some labels for the inputs and outputs. However, you had to know what things like “s1_fb1” meant to understand that that was an input.   We can go back to the original EPFG_Mashup, make some modifications for greater clarity, and those changes will also carry over to our new Mashup.       1. Reopen the old EPFG_Mashup on the Design tab.       2. Move all of the Widgets down to leave some extra room at the top.       3. Drag-and-drop two Divider Widgets onto the Canvas above both the Inputs and Results columns.       4. Select a Divider Widget, and go to its Style Properties.       5. Expand Base > Line to reveal the background Style Property.       6. Click on the default gray color to see the available options.       7. Choose the built-in black at the bottom, and click Select.       8. Make the same modification to the other Divider Widget.       9. Drag-and-drop two more Label Widgets onto the Canvas above the two columns.       10. Change their LabelText Properties to Inputs and Results, respectively.     Change Background and Size       1. From the Explorer tab in the top-left, select the container.       2. Select the Style Properties tab in the bottom-left and expand Base > Container.       3. Change the background Style Property to a color you prefer.       4. With the container still selected in the Explorer tab, drag the corners of the Mashup to reduce its size.       5. You could even move the Results column over, place the Auto Refresh Widget underneath, and then reduce the container size even further.       6. Click Save.     View Mashup Thus Far   With the changes to the previous EFPG_Mashup now complete, let’s ensure that everything carried over to our new Mashup.       1. Return to EEFV_Mashup.       2. Click Save.       3. Click View Mashup.   Note how the various changes we made to the base Mashup are also being shown, via a Contained Mashup Widget, in our new Mashup.   Splitting out functionality to a separate Mashup that is then embedded where needed is a great way to re-use content and simplify development.       Step 6: Add Chart   Our original Mashup (which has now been embedded in our new one) shows the instantaneous analytical results based on the inputs coming from the Edge MicroServer (EMS).   However, when investigating remote customer issues, it might be helpful to see some historical trends. A temporary "blip" of a low-grease indication might be worrisome, but it may not require immediate intervention unless the issue was occuring consistently or for extended periods of time.   Fortunately, creating a historical record is relatively simple in ThingWorx Foundation.   All that is really needed is a place in which to store the past records.   One of the easiest such storage methods is a Value Stream.       1. In ThingWorx Foundation, click Browse > Data Storage > Value Streams.       2. Click + New.       3. On the Choose Template pop-up, select ValueStream and click OK.       4. In the Name field, type EEFV_ValueStream.       5. If Project is not already set, search for and select PTCDefaultProject.       6. At the top, click Save.     Link Value Stream and Begin Storage   Now that we have a Value Stream to act as a storage location, we want to link it to EdgeThing.   After EdgeThing knows where to store historical data, we can simply instruct it which Property we want to archive by setting it to Logged.       1. Return to EdgeThing and its General Information tab.       2. In the Value Stream field, search for and select EEFV_ValueStream.       3. Click Save.       4. Still on EdgeThing, click Properties and Alerts.       5. Click Result_low_grease_mo to trigger the slide-out from the right-side.         6. Check Logged.       7. Click the Check icon in the top-right to close the slide-out.       8. Click Save.     Add Line Chart and Data   As per most guides in this Learning Path, it is assumed that you have an active connection to the EMS Engine Simulator and have your Analytics Event currently set to active.   This provides both the engine-sensor inputs and the analytical results for our Mashup.   After adding the Value Stream above, you'll need to let it run for a bit for the historical data to be archived. After it's run for a while and we have a valid history build-up, you can display that history in a Line Chart.       1. Return to EEFV_Mashup on the Design tab.       2. Click on the top-right section to select it.         3. From the Widgets tab, drag-and-drop a Line Chart onto the top-right section.         4. In the top-right of Mashup Builder, ensure the Data tab is selected.         5. Click the green + button.         6. On the Add Data pop-up in Entity Filter, search for and select EdgeThing.       7. In Services Filter, type queryprop.       8. Click the right arrow button besides QueryPropertyHistory.       9. Check Execute on Load.         10. Click Done.       11. Expand Data > Things_EdgeThing > QueryPropertyHistory > Returned Data.       Bind Data and View Mashup   Now that we have both our method of displaying the historical data, i.e. a Line Chart, as well as a method to bring backend data into the Mashup, i.e. QueryPropertyHistory, we can bind them together and see how our Mashup is progressing.       1. From the right under the Data tab, drag-and-drop EdgeThing > QueryPropertyHistory > Returned Data > All Data onto the Line Chart in the top-right of the Canvas.         2. On the Select Binding Target pop-up, click Data.         3. With the Line Chart selected, explore its Properties in the bottom-left.       4. Change XAxisField to timestamp.         5. Click Save.       6. Click View Mashup.     Your own Line Chart will vary depending on what values your Engine Simulator is sending to Foundation and Analytics.   NOTE: Remember that the Analysis Event needs to be Enabled for new values to be fed into Result_low_grease_mo.     Click here to view Part 3 of this guide.  
View full tip
    Step 3: Important Factors   If the company cannot ship or deliver their products fast enough, that will cause food waste and less revenue. At the same time, having nonstop access to meaningful data about the logistics side of the company provides a new level of decision-making capabilities.   Let’s first see what some of the pitfalls are that causes bad logistics or room for improvement. We can keep these items in mind as we work on our application.   Customer behavior – More attention can be put on how customers are shopping in certain areas. It’s not enough to know what areas are buying the most products and send them more shipments. Deadhead miles and load management will help save unnecessary costs. Shipment tracking and route planning – The traveling salesman problem is one that scientists have been working on for ages. There is no one solution to this problem, but there are many bad ones. Planning methods and routes is almost magic, but the more methodical the process, the more can be saved here. Something as simple and selecting the routes based on the number of right turns to reduce gas can save millions on yearly gas expenses. Method of travel utilization – Sea. Air. Road. Train. Each method has its benefits and down sides. When you pick a method, also incorporate how to utilize all the space provided. This could be using smaller boxes, a different type of packaging material, or playing Tetris in a trailer.   Customer Models   Understanding your customer and their habits is of utmost importance. We'll start by creating some of the base models used for customers in this applications. You will build on top of these models as you progress through this learning path.   In the ThingWorx Composer, click the + New in the top left of the screen.   Select Data Shape in the dropdown.   In the name field, enter Fizos.Customers.DataShape. All of our customers will be based off this Data Shape. Set the Project (ie, PTCDefaultProject) and click Save to store all changes. Click on the Field Definitions tab and click the + Add button to add new Field Definitions.   Add the list of Properties below:  Name       Base Type      Aspects                           Description ID Integer 0 minimum, primary key, default 0 Row identifier UUID String N/A String used as unique identifer across multiple platforms Type String N/A Type of customer (individual or another company) Factors Tags Data Tag This will hold the different type of data points or tags that will help to analyze a customer's characteristics and behavior Name String N/A Customer name Email String N/A Customer email Address String N/A Customer address Phone String N/A Customer phone number   The Properties for the Fizos.Customers.DataShape Data Shape should match the following:   7. In the ThingWorx Composer, click the + New in the top left of the screen.   8. Select Data Table in the dropdown and select Data Table in the prompt.   9. In the name field, enter Fizos.Customers.DataTable. Our differing types of customers will fall under this template.   10. For the Data Shape field, select Fizos.Customers.DataShape. 11. Set the Project (ie, PTCDefaultProject) and click Save to store all changes.   12. This entity will be used to house our data and provide assistance with our analytics. Vehicle Models   To build a plan for your logistics solutions, you first need to have the data necessary for your vehicles and factories. Let's begin housing this data to help us with our planning. In the ThingWorx Composer, click the + New in the top left of the screen.   Select Data Shape in the dropdown.   In the name field, enter Fizos.Vehicles.DataShape. All of our vehicles will be based off this Data Shape. Set the Project (ie, PTCDefaultProject) and click Save to store all changes.   Add the list of properties below: Name          Base Type       Aspects                               Description ID Integer 0 minimum, primary key, default 0 Row identifier FactoryID Integer 0 minimum, default 0 Factory row identifier Location Location N/A String used as unique identifer across multiple platforms Features Tags Data Tag This will hold the different type of data points or tags that will help to plan what this vehicle can and will build Size String N/A Factory size   The properties for the Fizos.Factories.DataShape Data Shape are as follows:   In the ThingWorx Composer, click the + New in the top left of the screen.   Select Data Table in the dropdown and select Data Table in the prompt.   In the name field, enter Fizos.Vehicles.DataTable. Our differing types of vehicles will be inside of this Data Table. For the Data Shape field, select Fizos.Vehicles.DataShape. Set the Project (ie, PTCDefaultProject) and click Save to store all changes.   This entity will be used to house our data and provide assistance with our analytics.   Factory Models   In the ThingWorx Composer, click the + New in the top left of the screen.   Select Data Shape in the dropdown.   In the name field, enter Fizos.Factories.DataShape. All of our factories will be based off this Data Shape. Set the Project (ie, PTCDefaultProject) and click Save to store all changes.   Add the list of properties below: Name        Base Type       Aspects                                  Description ID Integer 0 minimum, primary key, default 0 Row identifier Location Location N/A String used as unique identifer across multiple platforms Features Tags Data Tag This will hold the different type of data points or tags that will help to plan what this factory can and will build Size String N/A Factory size   The properties for the Fizos.Factories.DataShape Data Shape are as follows:     In the ThingWorx Composer, click the + New in the top left of the screen.   Select Data Table in the dropdown.   In the name field, enter Fizos.Factories.DataTable. Our differing types of factories will be inside of this Data Table. For the Data Shape field, select Fizos.Factories.DataShape. Set the Project (ie, PTCDefaultProject) and click Save to store all changes.   This entity will be used to house our data and provide assistance with our analytics.   Centralized Logistics   Our application needs an efficient system of logistics. We already have sensors for our food entities, so see below how we work to move in the right direction. We'll be using a Thing Template to allow our new services to be overriden later if we so choose.   In the ThingWorx Composer, click the + New in the top left of the screen.   Select Thing Template in the dropdown.   In the name field, enter Fizos.Logstics. All of our product line will fit this abstract entity. For the Base Thing Template field, select GenericThing. Set the Project (ie, PTCDefaultProject) and click Save to store all changes.   Add the list of Services below. The level of the complexity in these Service vary based on how you would like to start your daily routine, the number of employees, number of deliveries and facilities, etc. Name                                    Return Type   Override    Async     Description PerformDailyDeliveries Nothing Yes Yes Start process of regular product deliveries.   The list of services should look like the following:     Click here to view Part 3 of this guide.
View full tip
  Step 4: Write Data to External Database   You’ve connected to the database, you’re able to query the database. Now let’s handle inserting new data into the database. The update statements and data shown below are based on the table scripts provided in the download. Examples of how the ThingWorx entity should look can be seen in the SQLServerDatabaseController and OracleDatabaseController entities that you've downloaded   Running an Insert   Follow the steps below to set up a helper service to perform queries for the database. While other services might generate the query to be used, this helper service will be your shared execution service. In the DatabaseController entity, go to the Services tab.     2. Create a new service of type SQL (Command) called RunDatabaseCommand. 3. Keep the Output as Integer. 4. Add the following parameter:   Name Base Type Required command String True         5. Add the following code to your new service:   <<command>>       6. Click Save and Continue. Your service signature should look like the below example.     You now have a service that can run commands to the database. Run your service with a simple insert.   There are two ways to go from here. You can either query the database using services that call this service, or you can create more SQL Command services that query the database directly. Let’s go over each method next, starting with a service to call the helper.   In the Services tab of the DatabaseController entity, create a new service of type JavaScript. Name the service JavaScriptInsert_PersonsTable. Set the Output as InfoTable, but do not set the DataShape for the InfoTable. Add the following code to your new service: try { var command = "INSERT INTO Persons (person_key, person_name_first, person_name_last, person_email, person_company_name, " + "person_company_position, person_addr1_line1, person_addr1_line2, person_addr1_line3, person_addr1_city, person_addr1_state, " + "person_addr1_postal_code, person_addr1_country_code, person_addr1_phone_number, person_addr1_fax_number, person_created_by, " + "person_updated_by, person_created_date, person_updated_date) VALUES ('" + key + "', '" + name_first + "', '" + name_last + "', '" + email + "', '" + company_name + "', '" + company_position + "', '" + addr1_line1 + "', '" + addr1_line2 + "', '" + addr1_line3 + "', '" + addr1_city + "', '" + addr1_state + "', '" + addr1_postal_code + "', '" + addr1_country_code + "', '" + addr1_phone_number + "', '" + addr1_fax_number + "', '" + created_by + "', '" + updated_by + "', '" + created_date + "', '" + updated_date + "')"; logger.debug("DatabaseController.JavaScriptInsert_PersonsTable(): Query - " + command); var result = me.RunDatabaseCommand({command: command}); } catch(error) { logger.error("DatabaseController.JavaScriptInsert_PersonsTable(): Error - " + error.message); }         5. Add the following parameter:   Name Base Type Required key String True name_first String True name_last String True company_name String True company_position String True addr1_line1 String True addr1_line2 String True addr1_line3 String True addr1_city String True addr1_state String True addr1_postal_code String True addr1_country_code String True addr1_phone_number String True addr1_fax_number String True created_by String True updated_by String True created_date String True updated_date String True         6. Click Save and Continue.   Any parameter, especially those that were entered by users, that is being passed into a SQL Statement using the Database Connectors should be fully validated and sanitized before executing the statement! Failure to do so could result in the service becoming an SQL Injection vector.   Now, let’s utilize a second method to create a query directly to the database. You can use open and close brackets for parameters for the insert. You can also use <> as a method to mark a value that will need to be replaced. As you build your insert statement, use [[Parameter Name]] for parameters/variables substitution and <<string replacement >> for string substitution.   1. In the Services tab of the DatabaseController entity, create a new service of type SQL (Command).   2. Name the service SQLInsert_PersonsTable. 3. Add the following code to your new service: INSERT INTO Persons (person_key ,person_name_first ,person_name_last ,person_email ,person_company_name ,person_company_position ,person_addr1_line1 ,person_addr1_line2 ,person_addr1_line3 ,person_addr1_city ,person_addr1_state ,person_addr1_postal_code ,person_addr1_country_code ,person_addr1_phone_number ,person_addr1_fax_number ,person_created_by ,person_updated_by ,person_created_date ,person_updated_date) VALUES ([[key]] ,[[name_first]] ,[[name_last]] ,[[email]] ,[[company_name]] ,[[company_position]] ,[[addr1_line1]] ,[[addr1_line2]] ,[[addr1_line3]] ,[[addr1_city]]]] ,[[addr1_state]] ,[[addr1_postal_code]] ,[[addr1_country_code]] ,[[addr1_phone_number]] ,[[addr1_fax_number]] ,[[created_by]] ,[[updated_by]] ,[[created_date]] ,[[updated_date]]);       4. Add the following parameter:   Name Base Type Required key String True name_first String True name_last String True company_name String True company_position String True addr1_line1 String True addr1_line2 String True addr1_line3 String True addr1_city String True addr1_state String True addr1_postal_code String True addr1_country_code String True addr1_phone_number String True addr1_fax_number String True created_by String True updated_by String True created_date String True updated_date String True         5. Click Save and Continue.   Examples of insert services can be seen in the provided downloads.     Step 5: Executing Stored Procedures   There will be times when a singluar query will not be enough to get the job done. This is when you'll need to incorporate stored procedures into your database design.   ThingWorx is able to use the same SQL Command when executing a stored procedure with no data return and a SQL query when executing a stored procedure with an expected result set. Before executing these services or stored procedures, ensure they exist in your database. They can be found in the example file provided.   Execute Stored Procedure   Now, let's create the service to handle calling/executing a stored procedure.   If you are expecting data from this stored procedure, use EXEC to execute the stored procedure. If you only need to execute the stored procedure and do not expect a result set, then using the EXECUTE statement is good enough. You're also able to use the string substitution similar to what we've shown you in the earlier steps.   In the DatabaseController entity, go to the Services tab. Create a new service of type SQL (Command) called RunAssignStudentStoredProcedure. Add the following parameter:   Name Base Type Required student_key String True course_key String True         4. Add the following code to your new service:   EXECUTE AddStudentsToCourse @person_key = N'<<person_key>>', @course_key = N'<<course_key>>'; You can also perform this execute in a service based on JavaScript using the following code: try { var command = "EXECUTE AddStudentsToCourse " + " @student_key = N'" + student_key + "', " + " @course_key = N'" + course_key + "'"; logger.debug("DatabaseController.RunAssignStudentStoredProcedure(): Command - " + command); var result = me.RunDatabaseCommand({command:command}); } catch(error) { logger.error("DatabaseController.RunAssignStudentStoredProcedure(): Error - " + error.message); }         5. Click Save and Continue.   Execute Stored Procedure for Data   Let's create the entity you will use for both methods. This can be seen in the example below:     In the DatabaseController entity, go to the Services tab. Create a new service of type SQL (Query) called GetStudentCoursesStoredProcedure. Set the Output as InfoTable, but do not set the DataShape for the InfoTable. Add the following parameter:   Name Base Type Required course_key String True         5. Add the following code to your new service:   EXEC GetStudentsInCourse @course_key = N'<<course_key>>'   You can also perform this execute in a service based on JavaScript using the following code:   try { var query = "EXEC GetStudentsInCourse " + " @course_key = N'" + course_key + "'"; logger.debug("DatabaseController.GetStudentCoursesStoredProcedure(): Query - " + query); var result = me.RunDatabaseQuery({query:query}); } catch(error) { logger.error("DatabaseController.GetStudentCoursesStoredProcedure(): Error - " + error.message); }       6. Click Save and Continue.   You've now created your first set of services used to call stored procedures for data. Of course, these stored procedures will need to be in the database before they can successfully run.     Click here to view Part 3 of this guide.
View full tip
  Learn how to store and display medical device data for a Service opportunity.   Guide Concept   In this guide, you’ll learn how to combine information from multiple Edge devices into a single, logical Thing.   You’ll then create a GUI to display this combined information (as well as retrieve new information on demand) to facilitate a “Medical Service Play”.     You'll learn how to   Create a Data Shape and Info Table Property to store Medical Data Create a Service to combine data from multiple Edge devices into a single, logical Thing Create a Mashup to view and retrieve Medical data   NOTE:  The estimated time to complete ALL parts of this guide is 60 minutes     Step 1: Medical Learning Path   So far in this Learning Path, you've been able to connect both an embedded controller (simulated by a Raspberry Pi) and a PC to ThingWorx Foundation.   This is important, as medical devices can be complicated pieces of technology controlled by multiple "intelligent" subsystems. It is not always practical (or desirable) to have these subsystems communicate with each other, even if they all need to work together to function optimally.   Fortunately, Foundation has the capability to combine relevant data from multiple Edge devices into a single, logical Thing.   In this step of the Learning Path, you will do just that to facilitate a "Service Play".   The scenario is that your company manufactures and services Magnetic Resonance Imaging (MRI) devices.     Rather than simply servicing the MRI when there is an issue (and after a very expensive device has been damaged from something going wrong), your company maintains a continuing service contract with the hospital to monitor the MRI and perform preventative maintenance on it BEFORE anything goes wrong.   The value proposition to the hospital is the ability to keep their expensive investment in perfect operating order rather than suffering an unexpected failure. In turn, your company reaps the benefits of receiving a steady source of income from said service contract.   In order to achieve this level of preventative maintenance, your company needs to constantly monitor the MRI's various functions.   The MRI is composed of multiple working parts, but for this scenario, we'll limit our Minimum Viable Product (MVP) Service Application to the following:   An embedded device which monitors various hardware elements (such as magnet temperature and remaining coolant) A Windows PC (common in hospital equipment) which is used by a Medical Technician to control the MRI In particular, it's important to note that this PC has access to patient medical data, which can be subject to Health Insurance Portability and Accountability Act (HIPAA) violations. Fortunately here again, it's possible to segregate this information into protected and non-protected sections to limit your company's liability. We'll only propogate non-protected, generalized information to Foundation, such as the total number of scans that have been run thus far. This can facilitate your company getting a connected device approved by a hospital worried about HIPAA-compliance.   To help you run through this guide, we'll also utilize a pair of "simulators" to mimic data coming from the EMS-es on the Pi and PC, rather than directly taking information from them. So if you had any issues with the previous steps getting the EMS running on these devices, you can still complete this guide without issue.     Step 2: Import Simulators   As mentioned, we'll be using a pair of simulators to mimic connections to both an embedded microcontroller and a PC, both of which are part of the MRI.   Perform the following steps to import the simulators.   Download and unzip the MDSD_Entities.zip file attached to this article. In the bottom-left of Foundation Composer, click Import/Export.   Click Import.   On the Import pop-up, click Browse. Navigate to the download location and select the MDSD_Entities.twx file.   Click Open.   Click Import.   Click Close.   Note how there are now several MDSD Entities. These represent Things connected to different parts of the MRI which are communicating to Foundation via the EMS Agent (as per the previous guides in this Learning Path).   Investigate Simulators   Since there are multiple sub-systems which are all communicating directly to Foundation (but we really only want to check the status of the MRI as one logical entity), we need to know what exactly is being communicated back.   What is being communicated was likely determined by your company's Edge Developers when they implemented the EMS agent on said sub-systems.   Perform the following steps to investigate the simulators.   Click MDSD_Embedded_Thing.   Click Properties and Alerts.   So the embedded microcontroller has sensors which are tracking the following:    Property                           Units                       Description Coolant Percent Percent Amount of coolant left to refrigerate the super-conducting magnets Field Strength Tesla Strength of the magnetic field Magnet Temperature Degrees Celsius Temperature of the magnets   Next, let's look at the other simulator. Return to Browse > All. Click MDSD_PC_Thing. Click Properties and Alerts.   The PC is tracking information from the MRI controlling software, including the following:   Property Units  Description Number of Scans Scans Aggregate count of all scans the MRI has performed since last reset SSD Space Open Megabytes Amount of space left on the hard-drive Unused RAM Megabytes Amount of RAM still available to the system   Both of these remote devices are communicating valuable information.   The embedded microcontroller is feeding us information about the hardware of the MRI itself. Refilling coolant as needed is likely one of the service contract stipulations and will be a regular service need. And a Field Strength drop or Magnet Temperature rise could indicate more significant issues which could damage the MRI if not promptly addressed.   The PC gives us information about the operation of the MRI. Hard-drive or RAM running low could indicate that the hardware specs of the PC need to be upgraded, while the Number of Scans can give us a rough estimate of how much refrigerant should have been used versus the currently available level. If only a handful of Scans have been run, but the amount of coolant has dropped by a significant amount, then there could be a leak somewhere which would need to be addressed.   The combination of the Embedded and PC data is enough for us to begin working on a constantly-monitoring application which will facilitate our Service Play.       Step 3: Create Data Shape   Now that we're aware of what information is coming from the separate sub-systems of the MRI, we need to combine them into a single, logical Thing for the purposes of a Service Play.   To do so, we'll create a Thing which represents the MRI as a whole. Additional sub-systems can be added to to the collective information of this Thing as is necessary. But, as stated, this is simply an MVP, so we'll stick to the embedded and PC sub-systems at present.   A good way to aggregate multiple data points into a single item is via an Info Table Property. However, any time you create an Info Table, you also need a Data Shape to format the "columns" of the spreadsheet-like Property.   For more information on the storage of "mass-data", please refer to the Methods for Data Storage guide.   Perform the following steps to create a Data Shape.   Click Browse > Modeling > Data Shapes.   Click + New. In the Name field, type MDSD_DataShape.   If Project is not already set, search for and select PTCDefaultProject. At the top, click Field Definitions.   Click + Add.   Embedded Definitions   We now want to add Field Definitions to the Data Shape which map the information that we want to collate between the various sub-systems.   We'll start with the Embedded Microcontroller Properties.   On the far-right in the Name field, type Coolant_Percent. Change the Base Type to Number.   At the top-right, click the "Check with a +" for Done and Add. In the Name field, type Field_Strength. Change the Base Type to Number.   Click the "Check with a +" for Done and Add. In the Name field, type Magnet_Temperature. Change the Base Type to Number.   Click the "Check" button for Done. At the top, click Save.   PC Definitions   Additional Definitions can be added at anytime as other sub-systems are included.   We'll now include the PC Properties.   Click + Add. In the Name field, type Number_of_Scans. Change the Base Type to Number.   Click the "Check with a +" for Done and Add. In the Name field, type SSD_Space_Open. Change the Base Type to Number.   Click the "Check with a +" for Done and Add. In the Name field, type Unused_RAM. Change the Base Type to Number.   Click the "Check" button for Done. At the top, click Save.   Timestamp   It might also be benificial to include a Timestamp of when the values of both the embedded microcontroller and PC were added.   Click + Add. In the Name field, type Timestamp. Change the Base Type to DATETIME.   Click the Check button for Done. Click Save.     Click here to view Part 2 of this guide.
View full tip
  Step 4: Simulated Model   Models are primarily used by Analytics Manager (which will be discussed in the next guide), but they can still be used to estimate the accuracy of predictions.   When Models are calculated, they inherently withhold a certain amount of data (~20%). The prediction model is then run against the withheld data. This provides a form of "accuracy measure".   The withheld-data is selected randomly, so you'll actually get a slightly different model and accuracy measure each time that you create a Model versus the same dataset.   On the left, click Analytics Builder > Models.   Click New….   In the Model Name field, enter simulated_model. In the Dataset field, select simulated_dataset.   Click Submit. After ~60 seconds, the Model Status will change to COMPLETED.     Select the model that was created in the previous step, i.e. simulated_model. Click View… to open the Model Information page.   As with Signals and Profiles, our Model is once again "too good". In fact, it's perfect.   The expected "Precision" is 1.0, i.e. 100%. The True vs False Positive rate shown in the graph goes straight up to the top immediately.   While you want a graph that is "high and left", you're very unlikely to ever see real-world scenarios such as shown here.   Still, you've been able to progress the process of using Foundation (and now Analytics) to build an analytical model of MotorCo's prototype engine.   What needs to happen now is to receive real world data from your R&D engineers.     Step 5: Upload Real World Data   In your process of using the EMS Engine Simulator, the idea has always been to get a headstart on the engine developers.   At some point, they would wire sensors into the EMS and start providing real world data.   In our scenario, that has now happened. Real world data is being fed from the EMS to Foundation, Foundation is collecting that data in an Info Table Property, and you've even exported the data as a .csv. file.   This new dataset is over periods of both good and bad grease conditions. The engineers monitoring the process can flip a sensor switch connected to the EMS to log the current grease situation as either good or bad at the same time that the vibration sensors are taking readings.   We will now load this real world dataset into Analytics in the same manner that we did earlier with the simulated dataset.   Download the attached analytics_vibration.zip file to your computer. Unzip the analytics_vibration.zip file to access the vibration_data_and_header.csv and vibration_metadata.json files. On the left, click Analytics Builder > Data. Under Datasets, click New....   In the Dataset Name field, enter vibration_dataset. In the File Containing Dataset Data section, search for and select vibration_data_and_header.csv. In the File Containing Dataset Field Configuration section, search for and select vibration_metadata.json.   Click Submit.     Step 6: Real World Signals and Profiles   Now that the real-world vibration data has been uploaded, we’ll re-run Signals and Profiles just as we did before.   Hopefully, we’ll start seeing some patterns.   On the left, click Analytics Builder > Signals. At the top, click New….   In the Signal Name field, enter vibration_signal. In the Dataset field, select vibration_dataset.   Click Submit. Wait ~30 seconds for Signal State to change to COMPLETED     The results show that the five Frequency Bands for Sensor 1 are the most highly correlated with determining our goal of detecting a low grease condition.   For Sensor 2, only bands one and four seem to be related, while bands two, three, and five are hardly relevant at all.   This is a very different result than our earlier simulated data. Instead, it looks like it’s possible that the vibration-frequencies getting pickup up by our first sensor are explicitly more important.   Profiles   We’ll now re-run Profiles with our real-world dataset. On the left, click Analytics Builder > Profiles. Click New….   In the Profile Name field, enter vibration_profile. In the Dataset field, select vibration_dataset.   Click Submit. After ~30 seconds, the Signal State will change to COMPLETED.     The results show several Profiles (combinations of data) that appear to be statistically significant.   Only the first few Profiles, however, have a significant percentage of the total number of records. The later Profiles can largely be ignored.   Of those first Profiles, both Frequency Bands from Sensor 1 and Sensor 2 appear.   But in combination with the result from Signals (where Sensor 1 was always more important), this could possibly indicate that Sensor 1 is still the most important overall.   In other words, since Sensor 1 is statistically significant both by itself and in combination (but Sensor 2 is only significant in combination  with Sensor 1), then Sensor 2 may not be necessary.     Click here to view Part 3 of this guide.
View full tip
    Generate engine-failure predictions and gain insight into your data with machine learning.   GUIDE CONCEPT   This guide will upload captured data from an Edge MicroServer (EMS) "Engine Simulator" to ThingWorx Analytics Builder.   Following the steps in this guide, 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.   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL parts of this guide is 60 minutes     YOU'LL LEARN HOW TO   Load an IoT dataset Generate machine learning predictions Evaluate the analytics output to gain insight     Step 1: Scenario   In this guide, we’re continuing the same MotorCo scenario, where an engine can fail catastrophically in a low-grease condition.   In previous guides, you’ve gathered and exported engine vibration-data from an Edge MicroServer (EMS).   The goal of this guide is to now import that previously-exported Comma-Separated Values (.csv) data into ThingWorx Analytics, and then create an analytical model for predictive maintenance.   Analytical model creation can be extremely helpful for the automotive segment in particular. For instance, each car that comes off the factory line could have an EMS constantly sending data from which an analytical model could automatically detect engine trouble.   This could enable your company to offer an engine monitoring subscription service to your customers.   This guide will show you how to build an analytic model of your engine to facilitate this monitoring service.     Step 2: Upload Simulated Data   This guide assumes that you are using either the hosted trial (with has both Foundation and Analytics pre-installed) or a combination of the Foundation and Analytics downloadable installers.   To confirm that Foundation is communicating with Analytics, perform the following steps:   On the ThingWorx Foundation left-side navigation column, click Analytics > Analytics Builder > Settings.   At the top-right in the Analytics Server Version field, ensure that you see an appropriate version number.     NOTE:  If you use your own dataset, it's possible that you're results in the following steps will differ from those created by the provided-dataset. If you were unable to generate a 30,000+ entry dataset in the last guide, then you may download testCSVfile.csv attached here,instead. You will also need to download and extract vibration_metadata.zip which describes each column of the dataset. On the left, click Analytics Builder > Data.   Under Datasets, click New....   In the Dataset Name field, enter simulated_dataset. In the File Containing Dataset Data section, search for and select testCSVfile.csv. In the File Containing Dataset Field Configuration section, search for and select vibration_metadata.json.   Click Submit. Note that the time it takes to import the dataset is determined by its size.       Step 3: Simulated Signals and Profiles    The Signals section of ThingWorx Analytics looks for the most statistically correlated single field in the dataset which relates to your selected goal.   This doesn't necessarily indicate that it is the cause of your goal, whether maximizing or minimizing. It just means that the dataset indicates that this single field happens to correlate with the goal that you desire.   On the left, click Analytics Builder > Signals.   At the top, click New….   In the Signal Name field, enter simulated_signal. In the Dataset field, select simulated_dataset.   Click Submit. Wait ~30 seconds for Signal State to change to COMPLETED     Unfortunately, our results aren't very good. Or, more accurately, they're too good.   Our simulated dataset has some noise in it from adding random values to our five frequency bands on each our two sensors. However, ThingWorx Analytics has instantly seen through that noise and discarded it. Instead, it's only detected that s2_fb5 isn't relevant.   If you look back at the Use the EMS to Create an Engine Simulator guide, you'll see that s2_fb5 has the same base value between both a "good grease" and a "bad grease" condition, i.e. a base of 190.   This does show already that Analytics is working, though. Since s2_fb5 didn't change between good and bad grease conditions, our Signal analysis is indicating that it's not relevant to our model.   Profiles   Now, let's do the same for a Profile.   The Profiles section of ThingWorx Analytics looks for combinations of data which are highly correlated with your desired goal.   On the left, click Analytics Builder > Profiles.   Click New....   In the Profile Name field, enter simulated_profile. In the Dataset field, select simulated_dataset.   Click Submit. Wait ~30 seconds for the Profile State to change to COMPLETED.     Just like with Signals, our Profile is too good. In fact, Analytics is indicating that just s1_fb2 by itself is the primary indicator of good vs. bad grease conditions.   This is likely due to random chance. The random noise added to s1_fb2 just happened to be slightly less than the other frequency bands, so everything else was discarded.   Regardless, ThingWorx Analytics is quickly seeing through our simulated data.   Next, we'll actually create a Model using the simulated dataset.     Click here to view Part 2 of this guide  
View full tip
    Use a Timer to record mass amounts of test data, and then export it as a Comma-Separated Values file.   GUIDE CONCEPT   Having an Edge MicroServer (EMS) Engine Simulator has allowed you to begin work on using ThingWorx Foundation for instrumenting a prototype engine.   However, the end goal is not to inspect the data manually, but to have ThingWorx Analytics perform an automatic notification for any issues.   In this guide, you’ll create a Timer to generate thousands of data points, and then export the dataset as a Comma-Separated Values (.csv) file for future use in building an analytical model of the engine.     YOU'LL LEARN HOW TO   Create a Timer Subscribe to a Timer to Trigger a Service Generate Mass Amounts of Test Data Import the CSV Parser Extension Create a File Repository Export the Test Data as a Comma-Separated Values (.csv) file Download from a File Repository   NOTE:  The estimated time to complete all parts of this guide is 30 minutes.     Step 1: Scenario   In this guide, we're finishing up with the MotorCo scenario where an engine can fail catastrophically in a low-grease condition.   In previous guides, you've gathered and exported engine vibration-data from an Edge MicroServer (EMS) and used it to build an engine analytics model. You've even put that analytical model into service to give near-immediate results from current engine-vibration readings.   The goal of this guide is to create a GUI to visualize those predicted "low grease" conditions to facilitate customer warnings.     This is a necessary step, as the end-goal is to automate failure analysis by utilizing ThingWorx Analytics, which builds an analytical model by importing a .csv file with several thousand data points.   Data storage, export, and formatting in this manner can be extremely helpful for the automotive segment in particular. For instance, each car that comes off the factory line could have an EMS constantly sending data from which an analytical model could automatically detect engine trouble.   This could enable your company to offer an engine monitoring subscription service to your customers.   But to enable automatic comparison of engine data to an analytical model, you must first generate and format sample data to build said model, and this guide will show you exactly how to do that.     Step 2: Create a Timer   In the previous Use the EMS to Create an Engine Simulator guide, you ended up with an EMS engine simulator from which Foundation could capture individual readings and store them in an Info Table Property.   But for ThingWorx Analytics, we need thousands of data points, if not tens-of-thousands.   Manually triggering the Service to generate that many data points would be tedious.   Instead, we'll create a Timer Thing off which we can trigger the automatic calling of the data-capture Service.   This guide assumes that you have already completed the Use the Edge MicroServer (EMS) to Connect to ThingWorx and Use the EMS to Create an Engine Simulator guides and have a working, active connection from the EMS Engine Simulator to ThingWorx Foundation.       1. Return to the ThingWorx Foundation Browse > All navigation.          2. Click MODELING > Timers.       3, Click + New.       4. On the Choose Template pop-up, select Timer and click OK.     5. In the Name field, type ESDS_Timer.       6. If Project is not already set, search for and select PTCDefaultProject.        7. In the Run As User field, search for and select Administrator.       8. On the Warning pop-up, click Yes.   Note that the Administrator user should only be utilized for testing and never in a production system.       9. Set the Update Rate to 2000.   The EMS updates values around every second, i.e. 1000ms, so we want a time longer than that.     10. At the top, click Save.       Step 3: Subscribe to the Timer   Now that we have a Timer, we can use its 2000ms (two seconds) Event generation to trigger something else.   In this case, we’ll use it to trigger the data-capture Service we created in the previous guide.      1. Click Browse > MODELING > Things.      2. Open EdgeThing and click Properties and Alerts.      3. Scroll down past the custom Properties to the Inherited Properties.      4. Under the Value column, ensure that isConnected is checked. If not, return to the previous guides and confirm that your EMS engine simulator is running.     Having ensured that the EMS engine simulator is still providing values to ThingWorx Foundation, we now want to create a Subscription, which will trigger off our earlier timer.      1. At the top, click Subscriptions.      2. Click + Add.      3. In the Name field, type ESDS_Timer_Subscription.      4. Under Source, select the Other entity radio-button.      5. In the Search Entities field, search for and select ESDS_Timer.      6. Check the Enabled box.      7. Expand the Inputs section.      8. In the Select an Event field, search for and select Timer.      9. Expand the Me/Entities section.      10. Expand the Services sub-section.      11. Scroll down until you find the custom recordService, and click the right-arrow beside it.      12. Click Save and Continue. Note that you should NOT click the top “Save”, as that will erase the Subscription.                     Step 4: Data Acquisition   With the progress so far, another entry is captured and added to the Info Table Property ever two seconds. We'll confirm that now.   The longer that you let the Subscription run, the more entries will be automatically captured in the infoTableProperty. ThingWorx Analytics can use this information to build an analytical model.   To do so, though, it needs thousands of entries. For example, we’ve gotten good model results with 30,000 data points. In general, more is better.   As such, your Subscription would need to run until you have gathered 30,000 entries in the infoTableProperty. Unfortunately, this can take roughly 15-16 hours.   You can simply let the timer run for a short time and then continue with this guide immediately.       1. At the top, click Properties and Alerts.       2. Click the Refresh button several times. Note that both the identifier Property and the count of the number of entries in the infoTableProperty are continually increasing.       3. Under the Value column, click the “pencil icon” for infoTableProperty to select Set value of property. It may take a few moments for the pop-up to load.         4. Note that various values coming from the EMS engine simulator.       5. At the top-right of the pop-up, click the X button.   Stop Data Gathering After achieving the dataset size you desire, you should stop gathering to prevent your dataset from growing arbitrarily large.        1. At the top of EdgeThing, click Subscriptions.       2. If it is not already expanded, click ESDS_Timer_Subscription.       3. Expand Subscription Info.       4. Uncheck the Enabled box.        5. Click Save and Continue.       Click here to view Part 2 of this guide.    
View full tip
Build a Predictive Analytics Model Guide Part 2   Step 5: Profiles   The Profiles section of ThingWorx Analytics looks for combinations of data which are highly correlated with your desired goal. On the left, click ANALYTICS BUILDER > Profiles. Click New....The New Profile pop-up will open. NOTE: Notice the Text Data Only section which is new in ThingWorx 9.3.         3. In the Profile Name field, enter vibration_profile. 4. In the Dataset field, select vibration_dataset. 5. Leave the Goal field set to the default of low_grease. 6. Leave the Filter field set to the default of all_data. 7. Leave the Excluded Fields from Profile field set to the default of empty. 8. Click Submit. 9. After ~30 seconds, the Signal State will change to COMPLETED. The results will be displayed at the bottom.                 The results show several Profiles (combinations of data) that appear to be statistically significant. Only the first few Profiles, however, have a significant percentage of the total number of records. The later Profiles can largely be ignored. Of those first Profiles, both Frequency Bands from Sensor 1 and Sensor 2 appear. But in combination with the result from Signals (where Sensor 1 was always more important), this could possibly indicate that Sensor 1 is still the most important overall. In other words, since Sensor 1 is statistically significant both by itself and in combination (but Sensor 2 is only significant in combation with Sensor 1), then Sensor 2 may not be necessary.     Step 6: Create Model   Models are primarily used by Analytics Manager (which is beyond the scope of this guide), but they can still be used to measure the accuracy of predictions. When Models are calculated, they inherently withhold a certain amount of data. The prediction model is then run against the withheld data. This provides a form of "accuracy measure", which we'll use to determine whether Sensor 2 is necessary to the detection of a low grease condition by creating two different Models. The first Model (which you will create below) will contain all the data, while the second Model (in the next step) will exclude Sensor 2. On the left, click ANALYTICS BUILDER > Models.   Click New….The New Predictive Model pop-up will open.   3. In the Model Name field, enter vibration_model. 4. In the Dataset field, select vibration_dataset. 5. Leave the Goal field set to the default of low_grease. 6. Leave the Filter field set to the default of all_data.         7. Leave the Excluded Fields from Model section at its default of empty.       8. Click Submit. 9. After ~60 seconds, the Model Status will change to COMPLETED.   View Model   Now that the prediction model is COMPLETED, you can view the results. Select the model that was created in the previous step, i.e. vibration_model. Click View… to open the Model Information page.   Review the visualization of the validation results. Note that your results may differ slightly from the picture, as the automatically-withheld "test" portion of the dataset is randomly chosen. Click on the ? icon to the right of the chart for details on the information displayed.   The desired outcome is for the model to have a relatively high level of accuracy. The True Positive Rate shown on the Receiver Operating Characteristic (ROC) chart are much higher than the False Positives. The curve is relatively high and to the left, which indicates a high accuracy level. You may also click on the Confusion Matrix tab in the top-left, which will show you the number of True Positive and True Negatives in comparison to False Positives and False Negatives.     Note that the number of correct predictions is much higher than the number of incorrect predictions.     As such, we now know that our Sensors have a relatively good chance at predicting an impending failure by detecting low grease conditions before they cause catastrophic engine failure.     Step 7: Refine Model   We will now try comparing this first Model that includes both Sensors to a simpler Model using only Sensor 1. We do this because we suspect that Sensor 2 may not be necessary to achieve our goal. On the left, click ANALYTICS BUILDER > Models.   Click New…. In the Model Name field, enter vibration_model_s1_only. In the Dataset field, select vibration_dataset. Leave the Goal field set to the default of low_grease. Leave the Filter field set to the default of all_data.   On the right beside Excluded Fields from Model, click the Excluded Fields button. The Fields To Be Excluded From Job pop-up will open. 8. Click s2_fb1 to select the first Sensor 2 Frequency Band. 9. Select the rest of the Frequency Bands through s2_fb5 to choose all of the Sensor 2 frequencies. 10. While all the s2 values are selected, click the green "right arrow", i.e. the > button in the middle. 11. At the bottom-left, click Save. The Fields To Be Excluded From Job pop-up will close.           12. Click Submit. 13. After ~60 seconds, the Model State will change to COMPLETED. 14. With vibration_model_s1_only selected, click View....   The ROC chart is comparable to the original model (including Sensor 2). Likewise, the Confusion Matrix (on the other tab) indicates a good ratio of correct predictions versus incorrect predictions.     NOTE: These Models may vary slightly from your own final scores, as what data is used for the prediction versus for evaluation is random. ThingWorx Analytics's Models have indicated that you are likely to receive roughly the same accuracy of predicting a low-grease condition whether you use one sensor or two! If we can get an accurate early-warning of the low grease condition with just one sensor, it then becomes a business decision as to whether the extra cost of Sensor 2 is necessary.   Step 8: Next Steps   Congratulations! You've successfully completed the Build a Predictive Analytics Model guide, and learned how to:   Load an IoT dataset Generate machine learning predictions Evaluate the analytics output to gain insight    This is the last guide in the Getting Started on the ThingWorx Platform learning path.   This is the last guide in the Monitor Factory Supplies and Consumables learning path.   The next guide in the Design and Implement Data Models to Enable Predictive Analytics learning path is Operationalize an Analytics Model.     Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Support Analytics Builder Help Center    
View full tip
  Step 4: Install and Configure   Before you install the plugin, ensure that software requirements are met for proper installation of the plugin.   Open The Eclipse IDE and choose a suitable directory as a workspace. Go to the menu bar of the Eclipse window and select Help->Install New Software… After the Install window opens, click Add to add the Eclipse Plugin repository. Click Archive… and browse to the directory where the Eclipse Plugin zip file is stored and click Open. NOTE: Do not extract this zip file. Enter a name (for example, Eclipse Plugin).   Click OK. Ensure that the Group items by category checkbox is not selected. Select ThingWorx Extension Builder in the items list of the Install window. Click Next and the items to be installed are listed. Click Next and review the license agreement. Accept the license agreement and click Finish to complete the installation process. If a warning for unsigned content is displayed, click OK to complete the installation process. Restart Eclipse. When Eclipse starts again, ensure that you are in the ThingWorx Extension perspective. If not, select Window->Perspective->Open Perspective->Other->ThingWorx Extension, then click OK.     NOTE: Opening any item from File->New->Other…->ThingWorx will also change the perspective to ThingWorx Extension.   You are ready to start a ThingWorx Extension Project!   Step 5: Create Extension Project   In this tutorial, you will create a ThingWorx extension that performs authentication based on your security needs.   While in the ThingWorx Extension Perspective, go to File->New->Project. Click ThingWorx->ThingWorx Extension Project.   Click Next. Enter the Project Name (for example, AuthenticatorExample). Select Gradle or Ant as your build framework. Enter the SDK location by browsing to the directory where the Extension SDK is stored. Enter the Vendor information (for example, ThingWorx Labs). Select the JRE version to 1.8. Click Finish. Your newly created project is added to the Package Explorer tab. The information from ThingWorx Extension Properties is used to populate the metadata.xml file in your project. The metadata.xml file contains information about the extension and details for the various artifacts within the extension. The information in this file is used in the import process in ThingWorx to create and initialize the entities.   Create New Authenticator   Select your project and click New -> Authenticator to create a new Authenticator.   In the new window, enter AwesomeCustomAuthenticator for the Name.   If no Server is available, create a Server using any available option. You will not need that for this guide. This Server option might be utilized based on your later needs. Enter a description to your Authenticator, such as Sample Authenticator that validates against the Thingworx User. Select Finish. You will be able to check these settings within the metadata.xml file inside of the configfiles  directory.   You will now need to add the stubs for the authenticate, issueAuthenticationChallenge, and matchesAuthRequest methods. See below for sample code and descriptions.   Method Description Constructor Needed to instantiate new objects of type AwesomeCustomAuthenticator. Instance member data/variable values in your Authenticator will not be available across requests. initializeEntity This method is called when the Authenticator Thing is saved in ThingWorx Composer, e.g. saving configuration table updates. authenticate The logic/implementation that is used to authenticate a HTTP request. issueAuthenticationChallenge Handles logic which follows authentication failure (e.g. logging an error). matchesAuthRequest This method determines if this Authenticator is valid for the authentication request type.   Below provides more information about each of these methods and some example source code:   Constructor:   A new instance of custom Authenticator class is created to handle each new HTTP request for authentication. Upon importing a custom Authenticator extension, that Authenticator is registered into AuthenticatorManager and can be managed in the ThingWorx Composer with the other system authenticators. When that custom Authenticator is enabled, it will be used in conjunction with the other configured Authenticators to attempt to authenticate HTTP requests. Any static data for each new authentication instance should be thread safe. Best to avoid putting very much logic here, even calls to get configuration or instance data (use authenticate method instead).   initializeEntity:   Read configuration data into properties as needed for Authenticator challenges. Write the LDAP server address to some static property for use across all future instances for use in Authenticator challenges. This would be a way to ensure the LDAP server location is configurable from within ThingWorx Composer. Best to update this only once (e.g. for when the first connection is made).   authenticate:   If the authentication logic/implementation fails to authenticate the HTTP request due to error in the logic or the HTTP request contained invalid data that does not pass authentication, then this implementation should throw an exception.   Example code below:   @Override public void authenticate(HttpServletRequest request, HttpServletResponse response) throws AuthenticatorException { String username = request.getHeader("User"), password = request.getHeader("Password"); if(username.isEmpty() || password.isEmpty()) throw new AuthenticatorException("User login info is empty"); try { // This section logs the latest login time and login user to a thing called MyThing // Subscribing to these properties via DataChange event will allow this information to be stored Thing LoginHelper = (Thing) EntityUtilities.findEntity("MyThing", ThingworxRelationshipTypes.Thing); LoginHelper.setPropertyValue("LatestLoginUser", new StringPrimitive(username)); LoginHelper.setPropertyValue("LatestLoginTime", new DatetimePrimitive(DateTime.now())); _logger.warn(DateTime.now() + " -- " + username + " login attempt"); // Checks that user exists and is enabled; throws exception if can't validate // May want to create user in ThingWorx if they don't exist AuthenticationUtilities.validateEnabledThingworxUser(username); // Checks that user exists and validates credentials through all configured DirectoryServices // (one is the internal directory of ThingWorx users, one could be LDAP if configured); // throws exception if can't validate AuthenticationUtilities.validateCredentials(username, password); // REQUIRED: tells rest of ThingWorx which user is logged in for purposes of permissions, etc. this.setCredentials(username); } }   issueAuthenticationChallenge:   This may not be used at all, or it may be used for alerting or logging. May be used for constructing and sending a response to the client so the client can ask the user to enter credentials again (i.e. authentication challenge). matchesAuthRequest:   Example code below. This sample code for Authenticator to automatically login the user with default username/password when specific URI used in web browser.   @Override public boolean matchesAuthRequest(HttpServletRequest httpRequest) throws AuthenticatorException { String requestURI = httpRequest.getRequestURI(); // Must access it from this URL and not from /Thingworx/Runtime/index.html#mashup=LogoutButtonMashup as // the Request URI in the latter case is always going to show as /Thingworx/Runtime/index.html if (requestURI.equals("/Thingworx/Mashups/LogoutButtonMashup")) return true; else return false; }   Below is another example of how to implement the matchesAuthRequest method. Of course, it’s not a safe method. Nevertheless, it provides input into a different way to handle things.   @Override public boolean matchesAuthRequest(HttpServletRequest request) throws AuthenticatorException { try { // DON'T DO THIS by itself -- getHeader returns null if it can't find the header, // so this is unsafe and may block other authenticators from attempting String value1 = request.getHeader("User"); String value2 = request.getHeader("Password"); // DO ADD THIS - this is safe // Optionally add some logging statement here to inform of missing headers if(value1 == null || value2 == null) return false; return true; } catch(Exception e) { // This won't normally hit. This is really for other, more complicated validation processes throw new AuthenticatorException("Missing headers"); } }   Step 6: Build Extension   You can use either Gradle or Ant to build your ThingWorx Extension Project.   Build Extension with Gradle   Right click on your project ->Gradle (STS)->Tasks Quick Launcher.   Set Project from the drop-down menu to your project name and type Tasks as build. Press Enter. This will build the project and any error will be indicated in the console window.   Your console window will display BUILD SUCCESSFUL. This means that your extension is created and stored as a zip file in your_project->build->distributions folder.   Build Extension with Ant   Go to the Package explorer -> your_project->. Right click on build-extension.xml->Run As->Ant Build.   Your console output will indicate BUILD SUCCESSFUL similar to the below text: build: [echo] Building AuthenticatorExample extension package... BUILD SUCCESSFUL Total time: 770 milliseconds   NOTE: This will build your project and create the extension zip in the AuthenticatorExample->build->distributions folder of your project.     Click here to view Part 3 of this guide.  
View full tip
  Use the Collection Widget to organize visual elements of your application.   GUIDE CONCEPT   This project will introduce the Collection Widget.   Following the steps in this guide, you will learn to display different values from a single dataset in real-time.   We will teach you how to utilize the Collection Widget to generate a series of repeated Mashups for every row of data in a table.     YOU'LL LEARN HOW TO   Create a Datashape to define columns of a table Create a Thing with an Infotable Property Create a base Mashup to display data Utilize a Collection Widget to display data from multiple rows of a table   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL 3 parts of this guide is 60 minutes.      Step 1: Create a Datashape    Create a Datashape   The Collection Widget uses a Service to dynamically define visual content.   The data must be in a tabular format (for example: Data Table, Info Table, or external Database-connection) in order for the Collection Widget to access it.   In this part of the lesson, we'll create a Data Shape to define the columns of the table.   In a subsequent step, we'll create an Info Table Property within a Thing in order to store the information.   In the ThingWorx Composer Browse tab, click Modeling > Data Shapes, + New              2.  In the Name field, enter cwht_datashape.                      3. If Project is not already set, search for and select PTCDefaultProject.         4. At the top, click Field Definitions          First Definition:          1. Click + Add to open the New Field Definition slide-out.          2. In the Name field, enter first_number.          3. Change the Base Type to NUMBER.          4. Check the Is Primary Key box. All Datashapes must have a single Primary Key, and the first Field is as acceptable as any other for our purposes here.                5. At the top-right, click the "Check with a +" button for Done and Add.   Second Definition:   In the Name field, enter second_number.       2. Change the Base Type to NUMBER.               3. At the top-right, click the "Check with a +" button for Done and Add.     Third Definition:   In the Name field, enter third_number.         2. Change the Base Type to NUMBER.               3. At the top-right, click the "Check" button for Done         4. At the top, click Save.                   Step 2: Create a Thing   Create a Thing   In the previous step, we created a Data Shape to define the Info Table Property columns.   Now, we will create a Thing, add an Info Table Property, format the Info Table Property with the Data Shape, and set some default values.   On the ThingWorx Composer Browse tab, click Modeling > Things, + New.           2. In the Name field, enter cwht_thing.         3. If Project is not already set, search for and select PTCDefaultProject.         4. Select GenericThing in the Base Thing Template field       Add InfoTable Property         1. At the top, click Properties and Alerts.        2. Click the + Add button to open the New Property slide-out.        3. In the Name field, enter infotable_property.        4. Change the Base Type to INFOTABLE.        5. In the Data Shape field, select cwht_datashape.        6. Check the Persistent checkbox.       First Default   Check the Has Default Value checkbox. A cwht_datashape icon will appear underneath.            2. Under Has Default Value, click the cwht_datashape button to open the pop-up menu which  sets the default values               3. Click the + Add icon.         4. Enter values in each number field, such as 1, 2, and 3.              5. At the bottom-right, click the green Add button.     Second Default   Click the + Add icon.         2. Enter values in each number field, such as 10, 20, and 30            3. At the bottom-right, click the green Add button       Third Default   Click the + Add icon.       2. Enter values in each number field, such as 100, 200, and 300            3. At the bottom-right, click the greenAddbutton           4.  At the bottom-right, click Save to close the pop-up menu               5. At the top-right, click the "Check" button for Done.       6. At the top, click Save          Click here to view Part 2 of this guide.
View full tip