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

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

IoT Tips

Sort by:
  Discover how ThingWorx Functions can be implemented in a compelling Mashup design.   Guide Concept   This project will introduce how to create complex user interfaces that are built by using simple Mashup functions.   Following the steps in this guide, you will build a web application with multiple layers. We will teach you how to create a professional user interface that effectively conveys information to users.     You'll learn how to   Navigate to other UIs Create expressions and validations Create event routers and data handling Create confirmation modals/pop-ups Create status messages   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: What Are Functions   In the Mashup Builder, we utilize Functions to create added capabilities in our Mashups. Whether we are navigating to another Mashup or triggering events based on some action. Functions are your best friends when creating more advanced Mashups.   Function  Description   Auto Refresh  Refreshes data automatically for widgets in a mashup.  Confirmation  Displays a confirmation dialog box.  Events Router  Routes multiple input sources to one output of the same type.  Expression  Evaluates JavaScript expressions.  Logout  Ends the current user session and redirects to a mashup or a Web page.  Navigation  Navigates from one mashup to another.  Status Message  Displays information, error, or warning messages in a mashup.  Validator  Validates data from input parameters by using JavaScript expressions.   In the next sections, we will cover some of these Functions and showcase how to add them to your Mashups.     Step 2: Create an Expression   Let's start things off by creating a simple Expression Function. This Expression will show or hide a label based on whether a checkbox is checked or not. This simple expression can be expanded to your use case.   It is VERY important to note that in an Expression Function (and also found in Services and Validation Functions) the output of the Function will be the result variable. Let's create our Mashup, then go over what is involved in an Expression.   In the ThingWorx Composer, click the + New at the top of the screen.   Select Mashup in the dropdown.   Select the Responsive layout then hit OK.   Set the Name to  MyFunctionsMashup. For the Project, click the + button and select PTCDefaultProject.    Under Project, click the blue Set as project context option. This will stop us from having to set the Project on every Thing we create. It should now match the following.    Click Save. Click on the Design tab at the top.   This Mashup will be where we create the Majority of our Functions and capabilities. Let's start adding to our Mashup.   Click the Layout tab. Scroll down and set the Orientation to Horizontal.   Click on the Widgets tab. Type in the Filter text box for Checkbox.   Drag and drop a Checkbox Widget to the Mashup Canvas. This Checkbox will dictate whether what we show for the coming Labels and Textbox. Type in the Filter text box for Button. This Button will dictate the event that triggers our Functions. Drag and drop a Button Widget to the Mashup Canvas.   Type in the Filter text box for Label. Drag and drop TWO (2) Label Widgets to the Mashup Canvas. We will only show one Label at a time and I'll show you how.   Type in the Filter text box for Text Field. Drag and drop a Text Field Widget to the Mashup Canvas.     We have the Widgets we need to show our Expression example. Let's start with connecting the Widgets to Functions.   Click the + button in the Functions section in the bottom right.    In the New Function popup, select Expression. Set the Name of the new Expression to isCheckboxChecked.   Click Next. In the new screen, click Add Parameter. Set the Name to this new parameter as checked. Set the Base Type as BOOLEAN.   Switch the Data Change Type to ALWAYS. Switch Output Base Type to BOOLEAN.   Add the following code to the Expression area.  if(checked) { result = true; } else { result = false; }   11. Click Done.   You've now created your first expression. This expression is an example of how easy it can be done. Let's add three three additional Expressions to have some fun.   Repeat steps 1-11 in the last section for TWO (2) new Expressions. Name these Expressions setFirstLabelVisbility and setSecondLabelVisbility. You should now have three total. Repeat steps 1-8 in the last section for ONE (1) new Expression. Name this Expression setTextFieldText. We should have a Parameter called checked. Click Add Parameter again to add a Parameter named input. This fourth Expression should match the following thus far:     Switch Output Base Type to STRING. Add the following code to the Expression area:  if(checked) {     if(input && input.indexOf("YES") >= 0) {     result = input + ", YES";     } else {         result = "YES";     } } else {     result = "NO";     }   6. Click Done.   This expression will see whether or not the Checkbox is checked, then output a string of YES or a simple NO. Let's setup our connections between Widgets and Expressions.   Ensure Expressions are visible and match the following.   Click on the Checkbox in the Mashup Canvas. Click the dropdown that appears.   Drag and drop the State Property to the checked Parameter of all FOUR (4) of the Expressions.   Your bindings should match the following after you're done with setting all four.   Expand the setFirstLabelVisibility Expression (if not already expanded).   Drag the Output to the first Label and select Visible   Expand the setSecondLabelVisibility Expression (if not already expanded).   Drag the Output to the second Label and select Visible.   Our labels are configured. Now let's setup our Text Field Widget.    Expand the setTextFieldText Expression (if not already expanded). Drag the Output to the Text Field and select Text.   Select the Button Widget in the Mashup Canvas.  Click the dropdown for the Button Widget. Drag and drop the Clicked Event to all FOUR (4) of the Expressions.   Your Button Widget should look like the following:   Select the Text Field Widget in the Mashup Canvas Click the dropdown for the Text Field Widget. Drag and drop the Text Property to the input Parameter of the setTextFieldText Expression. Click Save. Click View Mashup. Play around and see all the work you've done. You may notice that both Label Widgets show or hide at the same time. To split when they will show or hide, update the code for one of the Label visibility Expressions to the following:    if(checked) {     result = false; } else {     result = true;     }   Click here to view Part 2 of this guide.
View full tip
    Step 3: Create A Tree Grid   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: Next Steps   Congratulations! You've successfully completed the Explore UI Functions guide, and learned best practices for building a complex Mashup that navigations, multiple data inputs, confirmations, and all working together effectively for an enhanced user experience.   Learn More   We recommend the following resources to continue your learning experience:    Capability     Guide Experience Object-Oriented UI Design Tips   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support Mashup Builder Support Help Center
View full tip
  Discover how ThingWorx advance tree grids and grids can be implemented in a compelling Mashup design.   Guide Concept   This project will introduce how to create complex user interfaces that are built by using Mashup grids and JavaScript services.   Following the steps in this guide, you will build a web application with advanced data displays. We will teach you how to create a professional user interface that effectively conveys information to users.   You'll learn how to   Create dynamic tree grids to display hierarchy. Create dynamic grids to display growing data number of data points.   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes       Step 1: What Are Dynamic Grids   In the Mashup Builder, we utilize Functions to create added capabilities in our Mashups. Whether we are navigating to another Mashup or triggering events based on some action. Functions are your best friends when creating more advanced Mashups.   Function  Description   Auto Refresh  Refreshes data automatically for widgets in a mashup.  Confirmation  Displays a confirmation dialog box.  Events Router  Routes multiple input sources to one output of the same type.  Expression  Evaluates JavaScript expressions.  Logout  Ends the current user session and redirects to a mashup or a Web page.  Navigation  Navigates from one mashup to another.  Status Message  Displays information, error, or warning messages in a mashup.  Validator  Validates data from input parameters by using JavaScript expressions.   In the next sections, we will cover some of these Functions and showcase how to add them to your Mashups.     Step 2: Create A Dynamic Grid   Let's start things off by creating a simple Expression Function. This Expression will show or hide a label based on whether a checkbox is checked or not. This simple expression can be expanded to your use case.   It is VERY important to note that in an Expression Function (and also found in Services and Validation Functions) the output of the Function will be the result variable. Let's create our Mashup, then go over what is involved in an Expression.   In the ThingWorx Composer, click the + New at the top of the screen.   Select Mashup in the dropdown.   Select the Responsive layout then hit OK.   Set the Name to  MyFunctionsMashup. For the Project, click the + button and select PTCDefaultProject.    Under Project, click the blue Set as project context option. This will stop us from having to set the Project on every Thing we create. It should now match the following.    Click Save. Click on the Design tab at the top. This Mashup will be where we create the Majority of our Functions and capabilities. Let's start adding to our Mashup.   Click the Layout tab. Scroll down and set the Orientation to Horizontal.   Click on the Widgets tab. Type in the Filter text box for Checkbox.   Drag and drop a Checkbox Widget to the Mashup Canvas. This Checkbox will dictate whether what we show for the coming Labels and Textbox. Type in the Filter text box for Button. This Button will dictate the event that triggers our Functions. Drag and drop a Button Widget to the Mashup Canvas.   Type in the Filter text box for Label. Drag and drop TWO (2) Label Widgets to the Mashup Canvas. We will only show one Label at a time and I'll show you how.   Type in the Filter text box for Text Field. Drag and drop a Text Field Widget to the Mashup Canvas.       We have the Widgets we need to show our Expression example. Let's start with connecting the Widgets to Functions.   Click the + button in the Functions section in the bottom right.    In the New Function popup, select Expression. Set the Name of the new Expression to isCheckboxChecked.   Click Next. In the new screen, click Add Parameter. Set the Name to this new parameter as checked. Set the Base Type as BOOLEAN.   Switch the Data Change Type to ALWAYS. Switch Output Base Type to BOOLEAN.   Add the following code to the Expression area.  if(checked) { result = true; } else { result = false; }   11. Click Done.   You've now created your first expression. This expression is an example of how easy it can be done. Let's add three three additional Expressions to have some fun.   Repeat steps 1-11 in the last section for TWO (2) new Expressions. Name these Expressions setFirstLabelVisbility and setSecondLabelVisbility. You should now have three total. Repeat steps 1-8 in the last section for ONE (1) new Expression. Name this Expression setTextFieldText. We should have a Parameter called checked. Click Add Parameter again to add a Parameter named input. This fourth Expression should match the following thus far:     Switch Output Base Type to STRING. Add the following code to the Expression area:  if(checked) {     if(input && input.indexOf("YES") >= 0) {     result = input + ", YES";     } else {         result = "YES";     } } else {     result = "NO";     } 6. Click Done.   This expression will see whether or not the Checkbox is checked, then output a string of YES or a simple NO. Let's setup our connections between Widgets and Expressions.   Ensure Expressions are visible and match the following.   Click on the Checkbox in the Mashup Canvas. Click the dropdown that appears.   Drag and drop the State Property to the checked Parameter of all FOUR (4) of the Expressions.   Your bindings should match the following after you're done with setting all four.   Expand the setFirstLabelVisibility Expression (if not already expanded).   Drag the Output to the first Label and select Visible.   Expand the setSecondLabelVisibility Expression (if not already expanded).   Drag the Output to the second Label and select Visible.   Our labels are configured. Now let's setup our Text Field Widget.    Expand the setTextFieldText Expression (if not already expanded). Drag the Output to the Text Field and select Text.   Select the Button Widget in the Mashup Canvas.  Click the dropdown for the Button Widget. Drag and drop the Clicked Event to all FOUR (4) of the Expressions.   Your Button Widget should look like the following:   Select the Text Field Widget in the Mashup Canvas Click the dropdown for the Text Field Widget. Drag and drop the Text Property to the input Parameter of the setTextFieldText Expression. Click Save. Click View Mashup. Play around and see all the work you've done.   You maybe notice that both Label Widgets show or hide at the same time. To split when they will show or hide, update the code for one of the Label visibility Expressions to the following:    if(checked) {     result = false; } else {     result = true;     }   Click here to view Part 2 of this guide.  
View full tip
  Create users, security groups, and provide a method to authenticate with LDAP.   Guide Concept   LDAP allows for a layer of security within your company or organization to be utilized for authentication or user management.   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 enable LDAP authentication in ThingWorx and configuring ThingWorx to connect to a LDAP server.   You'll learn how to   How to enable LDAP Authentication on ThingWorx Configuring ThingWorx to connect to an LDAP server Importing users from LDAP   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 60 minutes     Step 1: Completed Example   Download the completed files for this tutorial: ApacheDSExample.xml. This guide will cover authentication with an ApacheDS LDAP server.   In this tutorial, we walk through security concepts within ThingWorx. 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.   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: Understanding Directory Services   ThingWorx provides built-in LDAP Directory Support for clear-text connections (port 389). In order to enable LDAP Authentication, a Directory Service Entity must be imported and configured. The sample download provided is setup for Apache DS. An Active Directory example and a OpenLDAP example are attached, but will not be covered here. Other LDAP providers will need a similar file.   Users can exist in any Directory Services location as all Directory Services will be tried in order of priority when a user logs in. For the default setting, LDAP Directory Service will have priority over the ThingWorx one once enabled. To modify this configuration on the provided example, follow the below steps (if you have not done so already, import the XML file that was provided into The ThingWorx Composer):   From the ThingWorx Composer, go to the SECURITY section and click Directory Service. Open the Directory Service Entity you imported, ApacheDS. Enable LDAP in the General Properties section by checkicking the Enabled checkbox.   4. (Optional) Set the priority for the authentication if you have multiple Directory Service entities configured: Use the Priority property to assign an order of authentication to log in. The lower the number the higher the priority (1 is the highest priority). 5. Click Save to save ApacheDS and enable LDAP authentication. ThingWorx will contact the LDAP server to check for the given username when a user then tries to authenticate. If the user is not found or if the authentication on the LDAP server fails then the ThingWorx Directory Service will be tried.     Step 3: Configure ThingWorx and ApacheDS   This section will create an LDAP server, create the connection, and configure LDAP utilizing ApacheDS and Apache Directory Studio. In order to fully run this example, you will need to initially create this server OR deploy this server to a ThingWorx accessible location.   If you do not have an LDAP server already setup, utilize the below instructions to get started. If you already have a LDAP server setup, skip to the Configure ThingWorx For LDAP Connection section to configure the connection in ThingWorx.   Create New LDAP Server and Connection:   Open Apache Directory Studio. Right-click in the LDAP Servers section and select New -> New Server.   Select your version of ApacheDS in the menu and click Finish.   Right-click the newly created LDAP server and select Open Configuration.   Update the Port for the LDAP server to 389 and uncheck the LDAPS server.   Click Partitions at the bottom of the configuration and click Add.   Set the new Partition ID to ThingWorx. Set the Suffix value of the Partition to ou=people, dc=thingworx.   Save and close the configurations. Right-click the LDAP server and select Run. Once the State of the LDAP server has changed to Started, right-click the LDAP server and select Create Connection.   Utilize the ApacheDS adding entries guide to create users for your new LDAP server then follow the below instruction to create the ThingWorx connection. Configure ThingWorx For LDAP Connection: The sample XML files provided are configured with the most common attribute for the platform. From the ThingWorx Composer, go to the SECURITY section and click Directory Service. Open the Directory Service Entity you imported, ApacheDS. Generally, only one Entity listed unless multiple authentication realms have been configured. Click Congifurations to bring up Directory Service configuration details. Update the configuration parameters for the LDAP server: server: The hostname of the LDAP server userIdAttribute: LDAP attribute that is used to uniquely identify the user logging in. This property should be set to the name of the attribute containing the user's username. port: Connection port for the LDAP server. LDAP standard port is 389. If the LDAP server's connection port is 636, it is very likely that the server is expecting LDAPS, which ThingWorx does not currently support. adminBindDN: The full distinguished name for the user that the ThingWorx server will use for browsing the LDAP directory tree. The user that is defined here must have Read permissions on the directory tree. Generic Format: uid=admin, ou=Users, dc=company, dc=com userBaseDN: Distinguished name for the parent organizational unit (OU) containing any user that will need to log in. *Generic Format*: ou=ThingWorxUsers, ou=Users, dc=company, dc=com adminPassword: The password for the user configured in adminBindDN above   Click Save to update the ApacheDS Directory Service.       Step 4: Import Users Into ThingWorx   Handling Password Configurations: User must have a corresponding ThingWorx user created on the server before a user can log into ThingWorx via LDAP. These users must be created manually before they can log into the ThingWorx server All User entities created on ThingWorx matching LDAP users must have a password set, otherwise LDAP will not be able to log in. This password should NOT be the user's LDAP password The password used within ThingWorx should be secure/randomly generated. If LDAP authentication fails, ThingWorx will fall back on the password set for this user. The code provided below generates a random password for the users it creates Custom Service for User and Password Generation: A custom service can be created on a Service-Providing Thing instance that creates a specific user and assign it a home mashup: A Service-Providing Thing is an entity that uses the *GenericThing** ThingTemplate. It does not store properties. Instead, it provides useful Services that retrieve and compile data from many Thing instances for use in Mashups and/or other services. To create a Service-Providing Thing: Create a new Thing, and name it LDAPServiceHelper. Set the Thing Template to GenericThing. Click Services and create a new Service called CreateLDAPUser. Set the Inputs to be the following: Username (STRING, required) HomeMashup (MASHUPNAME, optional) Use the following for the source code: // ThingWorx will fall back on ThingWorx Directory Service (Local authentication) // if LDAP authentication fails, which means the password that we have to set for // the new user could also be used to log the user in. // Using a random string will make it highly unlikely that a user / attacker can // use the ThingWorx password to log in. var randompass = Math.random().toString(36).slice(-10); var params1 = { name: Username, password: randompass, description: "Generated LDAP User" }; Resources["EntityServices"].CreateUser(params1); // By default non-admin users will be directed to SQUEAL. // If there is a specific mashup that the user should see instead, // the following code will configure it based on the HomeMashup optional parameter. // The mashup passed to this service must exist. if (HomeMashup !== null) { var params2 = { name: HomeMashup }; Users[Username].SetHomeMashup(params2); } 6. Click Done. 7. Click Save.   Execute the newly created Service for each user in the LDAP system. Once all users have been imported (or at least the ones who need immediate access) the Directory Service must be enabled for ThingWorx to begin authenticating users via LDAP.       Step 5: Next Steps   Congratulations! You've successfully completed the Enabling LDAP Authentication in ThingWorx tutorial, and learned how to:   How to enable LDAP Authentication on ThingWorx Configuring ThingWorx to connect to an LDAP server Importing users from LDAP Auto assigning to user groups based on LDAP membership Learn More We recommend the following resources to continue your learning experience:    Capability   Guide Secure Create An Authentication Extension Secure Configure Permissions   Additional Resources If you have questions, issues, or need additional information, refer to:    Resource         Link Community Developer Community Forum Support Extension Development Guide  
View full tip
    Step 8: Learn More About Widgets   For more details on how to use and customize Widgets highlighted in this guide, refer to:    Widget            Link to How-To Layout Customizable and Responsive UI Gauge Display Property Values with a Gauge Style Define Your UI Style Navigation Customizable and Responsive UI Google Map Display Geolocation Data in Your UI     Step 9: Next Steps   Congratulations! You've successfully completed the Design an Effective UI guide, and learned best practices for building a complex Mashup that includes maps, menus, and detail sections all working together effectively for an enhanced user experience.   Learn More   We recommend the following resources to continue your learning experience:     Capability    Guide Experience Object-Oriented UI Design Tips   Additional Resources   If you have questions, issues, or need additional information, refer to:     Resource      Link Community Developer Community Forum Support Mashup Builder Support Help Center
View full tip
    Step 5: Collection Widget   A Collection widget is used to display information from a collection of Things. Similar to a Grid Widget, the Collection widget gives you complete control over how data is displayed by binding data to an embedded static Mashup.   In the first part of this step we will create a static Mashup with Parameters bound to its widgets. Next, we will configure a Collection widget to use the static Mashup we create. In the next step we will customize the Collection styling.   Create Static Mashup   Click the Browse tab on the far left of Composer, in the Visualizations section, click Mashups . Click + New to create a Mashup. Select Static Mashup, then click OK.   Name your Mashup TractorListFormat If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. Click Save. Click the Design tab If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. In the Layout tab, under Container > Positioning, Click Static, then scroll to Container Size, and click Fixed Size NOTE: A Static Mashup maintains fixed widget sizes and spacing, as opposed to a Responsive Mashup that will dynamically change widget sizes and spacing to use the available window area. Click the Width property and set it to 200 and the Height property to 60   In the lower left panel, click the Style tab and click the X to remove the default Style. Click the + icon, then select DefaultImageBorderStyle to remove all styling. NOTE: The default Mashup styling is removed so it will not override the sidebar and parent Mashup styling. Scroll to the Width property and set it to 200 and the Height property to 60 Click the Widgets tab and type label in the filter text box. Drag and drop two Label Widgets onto the upper left of your static Mashup.   Add Parameters to Mashup Select the Explorer tab then select the top level Mashup Click Configure Mashup Parameters from the drop-down menu in the upper left of the Mashup canvas.   Click the Add Parameter button. Type firstLine in the Name field and select a Base Type of STRING. Click Add Parameter again and name this parameter secondLine also with a Base Type STRING.   Click Done to return to Mashup Builder.   Bind Parameters to Widgets   Click the drop-down in the upper left of the Mashup canvas, then select Configure Bindings Click firstLine from the Properties list on the left. Clicking the drop-down arrow and click Add Source to display the Mashup entities that can be bound to the Mashup parameter named firstLine.   Select the checkbox next to the top LabelText property.   Click Done to return to the Configure Bindings pop-up. Click secondLine, then Binding Targets, and select the checkbox next to the bottom Label Text property, then click Done Click Done to close Configure Bindings pop-up and return to Mashup builder. NOTE: The Mashup parameters and bindings are displayed in the Connections panel at the bottom. Click Save before continuing to the next step.   Bind Data to Collection   Return to the main Mashup then drag and drop a Collection widget onto the top area of the left side bar. In the Collection Properties panel, set the View property to Table Scroll to the Mashup property, click the wand icon and browse to the name of the static Mashup created above. Drag the All Data source from the data panel on the right onto the Collection widget, then click Data in the Select Binding Target pop-up.   Set UIDField property and SortField to SerialNumber.   Drag the All Data source from the data panel on the right onto the Collection widget, then click Data in the Select Binding Target pop-up.   In the Collection Properties panel, scroll to MashupPropertyBinding and click *Add Enter the text below, then click Done: { "SerialNumber": "firstLine", "ModelNumber": "secondLine" } NOTE: This JSON property binds the SerialNumber and ModelNumber properties in the data source to the the firstLine and secondLine parameters in the embedded mashup   9. Save the Mashup and click View Mashup.   10. Test the Mashup and you will see the navigation panel on the left is showing data and is linked to the Google Map widget in the center.       Step 6: Customize Collection   The Collection uses default styling and no images. In this part of the exercise, we will replace the blue bar that indicates the selected row with a custom icon and modify the default styles so that the left panel's background color is shown.   Right-click on each of the images below to download and save them for use in the next step.     We will upload these images to create new Media entities and apply them to the Repeater widget.   Select the Browse folder icon on the far left of Composer, in the Visualization section click Media Click the + New to create a new Media entity and enter a name for the un-selected tractor image. Click Change in the Image section, then browse to the saved image. Click Open, then Save. Repeat these steps to create a Media entity for a selected tractor Open the static TractorListFormat mashup that controls the Collection widget formating Click and drag an Image widget onto the mashup In the lower left panel, in the SourceURL property, click the wand icon to select the unselected tractor image. Change both the Width and Height properties to 50 pressing Tab after each entry to record them.   Click the Explorer tab in the top left, click the top-most Mashup entity, then click the Style Properties tab Cick the X in the Style property and select DefaultImageBorderStyle to remove all styling, then click Save Click the More drop-down at the top of Composer and click Duplicate   Enter TractorListSelectFormat for the name and click Save then click the Design tab Click on the tractor image, then, the lower left, click the wand icon in the SourceURL property and select the selected tractor image and Click Save   Open your original Mashup and click on the Collection widget in the Mashuo Builder canvas. Scroll to the SelectedMashupName Property and click the + to select TractorListSelecteFormat.   Click Save for the Mashup, then View Mashup to see your Mashup with customized icons.   The default black text on green is a little hard to read. The steps below will change the text colors to make the data more readable. Open the TractorListSelectFormat Mashup then click on the top Label widget to change the color of the text. Click the Style Properties tab and expand Base and Label In color property select yellow and select Bold in the font-weight property before clicking Save. Select the other Label widget and assign a light grey color for the color then save the embedded Mashup. Reload the runtime view of the Mashup to see the results.     Step 7: Detail Panel   The right sidebar has a simple Image of a tractor along with product-specific information shown in Gauges and Value Displays.   The right sidebar contains two tabs in a Tabs - Responsive widget. The tabs are used to selectively hide and display groups of functions and data. The orange button labeled "View Vehicle Specs" is a Navigation widget that opens a pop-up window with other detailed product information. The colored range indications on the right Gauge were created by configuring the gauges ValueFormatter property to use State Formatting.   Add Tab Widget   Open the original, main Mashup and enter tab in the Widget panel search field. Drag and drop a Tabs widget onto the Right Sidebar.   Scroll to the Tab1Name property and enter Tractor Details. NOTE: This guide only covers configuring one of the two tabs added to the Mashup. Using the skills you've practiced thus far, feel free to add additional information to the tabs on your Mashup. Uncheck the RoundedCorners property. Click the Layout tab and click the radio button under Container > Orientation > Vertical   Add ValueDisplay Widgets   Type value in the Widget search box then click and drag a Value Display Widget onto Tab 1. In the Property panel, scroll to the Label property and enter Serial Number In the Data panel, expand Selected Row(s) then drag the SerialNumber property onto the Value Display widget and click Data when the Select Binding Target pop-up is displayed.   Drag another Value Display Widget onto the tab widget below to the first one and enter Name for the Label property. Drag name from the Selected Row(s) onto the second Value Display and then click Data. NOTE: Be sure to select data sources under Selected Row(s) so that data displayed will correspond to the tractor selected from either the map or the left side menu. Save the Mashup then click View Mashup to see all three panels working together to show data.   Add Gauges   Enter gauge in the Widget search box then click and drag a Gauge Widget onto Tab 1. In the Properties panel, enter 3000 for the MaxValue property and RPM in the Legend property. In the Data panel, expand Selected Row(s) then drag CurrentRPM onto the Gauge widget and click Data when the Select Binding Target pop-up is displayed. Drag another Gauge widget onto the canvas next to the first one and enter MPH for the Legend property. Drag CurrentSpeed from the Selected Row(s) onto the second Gauge, then click Data.   Click here to view Part 3 of this guide.
View full tip
  Discover how ThingWorx Widgets can be implemented in a compelling Mashup design.   Guide Concept   This project will introduce how to create complex user interfaces that are built by combining simple Widgets and basic styling.   Following the steps in this guide, you will build a web application showing both geographic and table based information.   We will teach you how to create a professional user interface that effectively conveys information to users.     You'll learn how to   Organize UI elements in a Mashup layout Use the Repeater widget effectively Use Styles to customize UI elements within a Mashup   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL parts of this guide is 60 minutes     Step 1: Top Level Layout   A Mashup like this does take some time to assemble, but is built by layering simple Widgets. In this guide, we will break down how this Mashup was created to give you a behind-the-scenes look and provide tips to use when developing your IoT application.     This professional-looking Mashup was created using only these Widgets:   Layout with both left and right sidebars and a footer Tabs - Responsive Repeater Navigation Image Property Display Gauge Google Map   The first Widget placed on this Mashup canvas was a Layout widget with both a Left and a Right Sidebar defined. The center portion of the layout has only one GoogleMap widget. The tractor icons displayed on the map were created by uploading a .png to create a Media entity then specifying the image as a custom MarkerStyle in the GoogleMap widget. In the following steps you will duplicate this Mashup.         Step 2: Import Data   In this step we will download and them import both a Thing Template and the sample data that are used throughout the exercise.   Download and save ConnectedTractors.xml which contains the Thing Template and example Things. In the lower left of Composer, click Import/Export, then Import.     In the Import From File pop-up, keep the defaults and click Browse.     Navigate to the ConnectedTractors.xml file you previously downloaded. Select the Entities file, then click Open. Click Import in the bottom right of the pop up, then click Close after file is successfully imported.     Step 3: Map Mashup   Follow the steps in this part of the lesson to create a Mashup with an organized, structured layout.   Create Mashup   Navigate to Browse > Visualization > Mashups.   Click + New.   Keep the defaults and click OK.   In the Name field, type TractorDemoMashup. If Project is not already set, click the + in the Project text box and select the PTCDefaultProject.   Click Save Click the Design tab in the Mashup Information panel Click the Layout tab, then click Add Left . Scroll down to Container Size, click Fixed Size then enter200 in the Width text box and press Tab to record your entry.   Click on the right side of your Mashup to select the larger container. Click Add Right before again scrolling down to Container Size, click Fixed Size then enter200 in the Width text box and press Tab to record your entry.        NOTE: The next step uses the Google Map Widget which may need to be downloaded and imported from IQNOX.com. A Step-by-step guide for using Google Maps with ThingWorx is available.   12. Click the Widgets tab on the top left of the Widget panel, then enter map in the search box of the Widget panel. 13. Click and drag the Google Map Widget onto the center area of the canvas. 14. Click Save   15. In the Data panel on the right click the + to add a data source for the Mashup. 16. Enter the name of the Template used to create the Things that will be shown on the Mashup. Click on the Template ConnectedTractor to use the sample data 17. Click the arrow to the right of GetImplementingThingsWithData, then click the Execute on Load check box before clicking Done.     Setup Map Data   In the Data panel on the right, if neccesary, expand the GetImplementingThingsWithData data source and then drag the All Data row onto the map widget.   Click Data in the Select Binding Target pop-up to connect the data source to the Data property of the Google Maps widget. In the Properties panel in the lower left, scroll to the LocationField property then select TractorLatLng   NOTE: The imported sample data provided for this lesson has a property named TractorLatLng that contains location information. Fields in the bound data with a type Location will be available in the drop down. 4. Click Save at the top of your Mashup. Click View Mashup to see the live map. NOTE: The map uses the standard markers, click on one of the markers to see that the marker changes to indicate that it is selected.     Customize Map Markers   In this part of the lesson we will show how to use a custom image for the map markers. Right-click on each of the images below to download and save them to use in the next step.       We will upload these images to create new Media entities and apply them to the Google Map widget. Click Browse > Visualization > Media.   Click + New. In the Name field, type TractorSelected.   If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. Under Image, click Change. Navigate to and select the TractorSelected.png file you just downloaded. On the navigation pop-up, click Open to close the pop-up and confirm the image selection. At the top of Foundation, click Save.    Repeat steps 1 through 8 for TracktorUnselected. Open your Mashup and click on the Google Map widget. Click on Style Properties tab in the lower left and scroll to the MarkerStyle Property and click on the Default map marker image, then click edit.   Click Style Information in the left panel, then clear the default image by clicking the X next to Image.   Click the + to select a new image then scroll to the Media entity you just created. In this case, the TractorUnselected media. Click Save. NOTE: The Google Map widget is packaged with default style entities. By editing these styles we will change the markers for all Mashups running on this ThingWorx server. In later steps we show how to create one time use Styles instead of modifying the default Styles.   14. Repeat steps 1 through 8 to create and assign the TractorSelected image for the SelectedMarkerStyle Property. 15. Click Save for the Mashup, then View Mashup to see the custom map icons.       Step 4: Navigation Panel   The left sidebar defines the green background color in its style and contains just one Collection widget with custom embedded Mashups specified for both the Selected and the Unselected items. The logo at the bottom is an image defined in the Footer style.   The Collection widget works by duplicating an embedded panel Mashup that controls the display of data from each entity in collection of entities.   Add Footer   Select the left side container of your Mashup, then click the Layout tab Click Add Bottom and scroll down to Container Size, click Fixed Size then enter 60 in the Height text box and press Tab to record your entry.   Click Save.   Style Sidebar   Next, we are going to add a custom background color and image to the sidebar footer.   Click the Explorer tab in the widget panel then select the top container for the left sidebar.   Click the Style Properties tab in the lower left properties panel, then click to expand Base and flexcontainer. In the background tex box, enter #39736C for a dark green color, then press Tab.   Click the top left container, then, in the Style Properties tab, click to expand Base and flexcontainer. Click X in background property   Click the lower left container, and also click X to remove the background property.   Right-click on the image below to download and save it for use when we add a footer in the next step.   Create a Media entity as we did for the map markers by clicking the Browse folder icon, then click Media in the Visualization section. Click the + New to create a new Media entity. Enter twxpwr in the Name field for the footer image. If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. Click Change in the Image section, then browse to the image you saved. Click Open, then Save.   Click in the lower-left footer container on your mashup, then click the Properties tab. Scroll to see the SourceURL property in the properties panel, then click the + to open the media selection window. Scroll to browse for the Media you just created.   Click the footer Media and then slick Save in Mashup Builder before continuing to the next step.     Click here to view Part 2 of this guide.
View full tip
    Step 3: Monitor SPC Properties   Once the properties have been configured, you are ready to progress on to SPC monitoring.   This is done by viewing the PTC.SPC.Monitoring_MU Mashup.   NOTE: Once a property has been configured for SPC monitoring, 2-5 minutes must pass before the accelerator has collected enough streaming values to perform SPC calculations. During this time, you may see an item that has 2 OOC rules violated; “Collecting Enough Data to Begin Monitoring” and “… to Compute Capability”.     Within Property SPC Status, click an item from the grid that has 0 in the OOC column. See that the Out of Control Rules area is blank, since there are no currently-violated SCP rules for that selected property. Both CP and CPK are above 1.0, showing that the process is capable. All the points in the charts are blue, as they do not violate any OOC rules. Within Property SPC Status, click an item from the grid that has a nonzero number in the OOC column.   See that the Out of Control Rules area has one or more rules listed that are currently being violated. Here, the rule being violated is Range Out of Control. One or more of the charts may have point(s) that are red. Here, you can see one of the points in the R chart is red, as it is above the Upper Control Limit. In the bottom-left, click Refresh Now.   Note that the datetime value of the date picker in the lower-left indicates the period to which the Mashup has updated. It is possible that Properties that were previously not in violation are now violating OOC rules; the opposite is also possible. Note that not all points that violate an OOC rule will display in red. Here, you can see that the rule 8 Consecutive Points Above Center Line is violated, but the corresponding points in the X-Bar Chart are not red. View the SPC status at a time from the recent past. In the lower-left, click date picker. Choose a datetime of 2-3 minutes in the past. You will see that the date picker reflects the datetime value you selected. All the Widgets in the Mashup are updated to reflect their status at that point in time. Enter continuous monitoring mode. Select any of the eight (8) items from the Property SPC Status area. To the left of the Refresh Now button, click the toggle. This will enable the Mashup to auto-refresh every 30 seconds. In the upper-right corner of the Property SPC Status area, click the gray arrow to expand the monitoring display.   Every 30 seconds, the monitoring display will update to show the most recent status for the item you selected.       Step 4: Next Steps   Congratulations! You’ve successfully completed the Deploy Statistical Process Control guide, and learned how to:   Configure multiple properties for SPC monitoring Identify abnormalities in streaming property values   Learn More   We recommend the following resources to continue your learning experience:    Site              Link Wikipedia Western Electric Rules Wikipedia Process Capability   Additional Resources If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support ThingWorx Help Center  
View full tip
    Configure streaming asset properties for SPC monitoring.   Guide Concept   Note: This guide is intended only as a starting point and is not a fully developed or supported solution. This accelerator has been developed using ThingWorx 8.5 and should not be used with any previous versions of the software.   This project introduces you to configuring Properties from your connected streaming assets for Statistical Process Control (SPC) monitoring.   Following the steps in this guide, you will learn how multiple connected assets and their Properties can be displayed in a hierarchy tree.   You will then configure these Properties using predetermined set points, and upper and lower control points for the assets.   Finally, you will learn to navigate the monitoring of the Properties.   We introduce some of the basic building blocks of an SPC accelerator, including important Things and Mashups. You will also use ThingWorx Timers to simulate streaming data.     You'll learn how to   Configure multiple properties for SPC monitoring Identify abnormalities in streaming property values   NOTE: The estimated time to complete this guide is 30 minutes     Step 1: Import SPC Accelerator   Before exploring Statistical Process Control (SCP) within ThingWorx Foundation, you must first import some Entities via the top-right Import / Export button.   Download and unzip PTC_StatisticalCalculations_PJ.zip and PTC_SPC_PJ.zip. These two files each contain a ThingWorx project of a similar name. Import PTC_StatisticalCalculations_PJ.twx first. Import PTC_SPC_PJ.twx once the other import has completed. Explore the imported entities.   Each of the projects contain multiple entities of various types. The most important entities you will use in this guide are as follows:    Entity Name                                   Description Motor_Pump1 Timer to simulate streaming data Motor_Blower1 Timer to simulate streaming data PTC.SPC.ConfigurationHelper Thing that manages the accelerator PTC.SPC.Configuration_MU Mashup for configuring SPC properties PTC.SPC.Monitoring_MU Mashup for monitoring SPC properties   Step 2: Configure Properties for SPC monitoring   You may configure SPC monitoring for multiple production lines, connected assets on those lines, and time-series Properties on those assets using the SPC accelerator.   This is done by viewing the PTC.SPC.Configuration_MU Mashup.   Follow these steps to configure an SPC Property.   Create a new production line   In the Enter New Production Line Name text field, type Line100. Click Add New Line.   Now you will see the new production line added to the Asset Hierarchy tree along the left. All production lines you’ve created (as well as their assets and the assets’ Properties) will be shown here.   In the lower-right, the SPC Property Configuration area has disappeared because the item selected in the Asset Hierarchy tree is the new line; only assets within lines can have streaming Properties.   Add a streaming asset to Line100   Within the Select Asset Thing entity picker, type Motor_Blower1. Click Add Asset for Line.   This asset has Properties that are streaming into ThingWorx. Multiple assets can be added to the same production line by selecting the line from the Asset Hierarchy tree and following the steps above.   If you select the new asset from the Asset Hierarchy tree, you will see that the list of Properties Eligible for SPC Monitor is shown in the SPC Property Configuration area. All Properties have the same default configuration associated with them.   Configure a property for SPC Monitoring   Below is a brief description of each of the configuration parameters:    Parameter           Description Sample Size Number of consecutive property values to average together. For example, a Sample Size of 5 will tell the accelerator to group every 5 property values together and calculate their average value. XBar Points Number of the most recent sample aggregations to display in the SPC Monitoring Mashup. This also affects SPC calculations. Capability Points Number of the most recent sample aggregations to use when populating the Capability Histogram in the SPC Monitoring Mashup. Set Point Value determined to be the set point for that particular property on the asset. Lower Design Spec Value determined to be the lower design spec for that particular property on the asset. This is used for capability calculations. Upper Design Spec Value determined to be the upper design spec for that particular property on the asset. This is used for capability calculations.   Select Pressure1 from the list of eligible properties. Enter the following values:  Properties                      Values Sample Size 5 Xbar Points 30 Capability Points 60 Set Point 73 Lower Design Spec 68 Uppder Design Spec 78   3, Select Xbar-R Chart. 4. Click Add or Update SPC Monitoring. 5. Pressure1 is added to the Asset Hierarchy tree underneath the Motor_Blower1 asset. 6. If you select this Property, you can modify the configuration and save it by clicking Add or Update SPC Monitoring.   Configure assets and Properties   Follow these steps using the following parameters:                                     Line Asset  Property  Sample Size Xbar Point Capability Points Set Points Lower Design Spec Upper Design Spec Chart Type 100 Motor_Blower1 Pressure1 5 30 60 73 68 78 Xbar-R 100 Motor_Blower1 Pressure2 5 30 60 78 68 89 Xbar-R 100 Motor_Blower1 Temperature1 5 30 60 50 44 56 Xbar-s 100 Motor_Blower1 Temperature2 5 30 60 85 73 97 Xbar-s 100 Motor_Pump1 Vibration10 5 30 60 150 108 190 Xbar-s 100 Motor_Pump1 Vibration11 8 60 100 200 168 220 Xbar-s 100 Motor_Pump1 Pressure100 5 30 60 100 84 118 Xbar-R 100 Motor_Pump1 Pressure200 5 30 60 90 84 97 Xbar-R   As you add assets to Line100 and configure their Properties, you will see the Asset Hierarchy tree grow. If you need to remove an asset or its associated Properties from the Asset Hierarchy tree, you may select that item, and click Remove Selected. For any item you remove, its child-items will also be removed.   Click here to view Part 2 of this guide.
View full tip
    Guide Concept   This project will introduce how to get your application ready for usage by actual users or ready to collect data.   Following the steps in this guide, you will be ready to present your finished application to users so they can benefit from its functionality. Deploying your application provides the ability for users to access it from anywhere, anytime and enables your edge devices to communicate with your application 24/7.   We will teach you how to deploy your ThingWorx IoT application to be ready for whatever experience you've molded it to be.     You'll learn how to   Create login screens, users and user groups Define security permissions Deploy application Identify and troubleshoot issues   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes     Step 1: Completed Example   Download the CompletedApplication.xml attached to this guide.  Within the downloaded file, you will find Entities referenced in this lesson, including a finished application that will be used for the deployment exercise. Import and utilize this file to see a finished example and return to it as a reference if you become stuck during this guide and need some extra help or clarification.   Keep in mind, this download uses the exact names for entities used in this tutorial. If you would like to import this example and also create entities on your own, change the names of the entities you create.       Step 2: Define Organization   In order to control access to your application, you first need to create an Organization. Think of the organization entity as your company or department. Once you define the organization, you will create Users and User Groups.   Organizations are hierarchical structures that allow you to assign visibility to entities in the ThingWorx Model. You can add users and group to each level within this structure.   Organizational Structure   This is the organization defined within the sample application download for this guide.  Entity Name                Entity Type      Description Constructors Organization High level of an organization. UpperManagement User Group Executives in the organization. HR User Group HR department in the organization. Management User Group First and second tier management in the company. Laborers User Group Skilled trade workers in the organization. ConstructorsGroup User Group Security group for all employees in the company. j.general User HR Department Employee a.jones User Skilled Laborer j.lewis User Manager i.jorden User CEO default_user User User used in trial version for all company roles.      Create Organization   Follow the steps below to create an Organization and make it login ready. Once your Organization is saved, you are provided with a login screen. Customize the login page to your liking with the General Information tab of the Organization after creating it.   In the ThingWorx Composer, click the + New at the top of the screen.     Select Organization in the dropdown.     Name your Organization Constructors. Set the Project field (ie, PTCDefaultProject) and click Save     Click Edit and select the Organization tab to see the hierarchy. With the top organization selected, in the Members search bar, search for the user you have created yourself and add them. Keep track of the user you added, they will be needed to log into the application later in this guide.            View Organization   From the Home page of Composer, filter for and select the Constructors Organization. The General Information tab shows the configurations for the login screen and resetting passwords. For more information on password resets, see the Password Reset Help Page. The Login Image is where you would put your logo or an image you would want users to see when they are logging into your application. The Home Mashup is the page you would like users to go to after they have passed the login prompt. The Login Style and Login Button Style are Style Definition properties. NOTE: If you keep these fields blank, the default configurations will be applied. You can create your own Style Definitions by following steps in our Styles and States Guide.   Create Organizational Units   Let's create the structors for our Organization. With the Constructors Organization open, follow the directions below:   Click the green + button under the structure you would like to expand. Name your Organization unit UpperManagement In the Members search bar, search for the user or user group you created and add it.     Click Save. Repeat the steps to create the full hierarchy of the organization and its members.     Setup Entity Visibility   Visibility is a simple form of access control. If an entity is visible to members of an organizational unit, then its members have access to the entity.   Select the Permissions tab of any Thing you created in Composer.     Filter and select Constructors in the Search Organizations field. Click Save.         Step 3: Security and Permissions   By Default, new Users have no permission configurations. Permissions can be defined for any Entity created on the ThingWorx platform. All Entities have permission control for both design time and run time.   Design time is the period in which changes can be made to the Entity in Composer. Run time is the period in which the application is running and calls are made.   Permissions should be set for each and every Entity within the application in order to keep it secure and maintain access to services.   Select the Permissions tab of any Thing you created in Composer (ie, ConstructorsBlog).   Select the Design Time or Run Time tab.   After selecting one, filter and select a User or UserGroup to set their permissions. Set the Allow, Deny or Inheritence markers to set permissions respectively.   The Inherit category allows a user to inherit permissions from the user group it belongs to.       Step 4: Deploy Application   ThingWorx Composer is set up to allow deployment in very simple steps. An application can run locally on a computer or remotely on a server as long as an Apache Tomcat server is installed on the same machine. Simply copy the URL that is generated when you click View Mashup within Composer. That is the URL to share with users so they can access your application.     If you plan to use a Login Screen, use the View Mashup URL generated from the Login Mashup you create. To view the login page of your application, type the following URL: [server]/Thingworx/FormLogin/ (ie, localhost/Thingworx/FormLogin/Constructors).   The login page for the sample application can be found at: [server]/Thingworx/FormLogin/Constructors.     To log in using this screen, type in the username and password of a user that is in the organization.   To use one of the example Users, set their password in the Composer and test it within the login prompt. Based on the permissions you set, users will have a different view of the application when they log in.         Step 5: Logging and Troubleshooting   There are two mechanisms that enable you a view into your application and what is happening behind-the-scenes, through the ThingWorx Composer Monitoring and the ThingWorx filesystem.   ThingWorx Composer Monitoring   ThingWorx provides pages to see all logs and communications between your ThingWorx instance, your applications, and edge devices using the Monitoring drop-down in the top navigation toolbar of your Composer. To see this page click Monitoring on the left menu, then select the option you would like to see.      Resource                  Usage Application Log This page will show you the log for your application and information on the processing running. Communication Log This page is used to show communication between your ThingWorx instance and outside sources. Configuration Log This page provides information into what is happening behind the scenes for your ThingWorx Composer and how it has been configured. Security Log This page highlights any information around access to the application, composer, or any security updates Script Log Logging information you have set for scripts running in your ThingWorx instance. Error Log Details for errors within your ThingWorx instance. Remote Things This page provides the list of Entities that are able to connect to edge devices, connected to your application, and even Entities that are currently disconnected.   ThingWorx File System   Log files for ThingWorx and your application can be found in the [Root]\ThingworxStorage\logs directory. The ROOT DIRECTORY is the folder in which ThingWorx has been running (ie, C:\ThingworxStorage\logs for Windows or /ThingworxStorage/logs for Mac or Linux).   Each log file corresponds to some of the content you can see in the Monitoring dropdown in the ThingWorx Composer.       Step 6: Next Steps   Congratulations you have completed the Deploy an Application How-To, and learned how to:   Create login screens, users and user groups Define security permissions Deploy application Identify and troubleshoot issues   The next guide in the Customize UI and Display Options to Deploy Applications learning path is How to Display Data in Charts.    Additional Resources   We recommend the following resources to continue your learning experience:    Capability    Guide Build Implement Services, Events, and Subscriptions Secure Configure Permissions     If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support Help Center  
View full tip
    Use ThingWorx Kepware Server as an OPC UA Client   GUIDE CONCEPT   This guide will explain how ThingWorx Kepware server can function as both an OPC UA Server, and a client to a remote OPC UA Server.   Following the steps in this guide, you will create a OPC UA server in Azure, then we will teach you how to use data from the OPC UA server in ThingWorx.       YOU'LL LEARN HOW TO   Create an OPC UA Server in Azure Configure Kepware as on OPC UA Client Connect Kepware to ThingWorx Foundation Monitor OPC UA data in ThingWorx Composer   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 60 minutes     Step 1: Overview Diagram   In this guide, ThingWorx Kepware Server will serve as both an OPC UA client, and a ThingWorx Foundation client. ThingWorx Kepware Server is able to connect through firewalls to provide a seamless, end-to-end connection from an OPC UA server to ThingWorx Composer. Two ThingWorx Kepware Server instances can be configured to provide a tunnel for transporting machine data across the internet.       This guide will show how to create an OPC UA server in Azure, then browse the server data using Kepware. We will create a ThingWorx Thing with a Property that dynamically represents the value on the remote server.     Step 2: Install ThingWorx Kepware Server   In addition to OPC UA, ThingWorx Kepware Server includes over 150 factory-automation protocols. ThingWorx Kepware Server communicates between industrial assets and ThingWorx Foundation, providing streamlined, real-time access to OT and IT data — whether that data is sourced from on-premise web servers, off-premise cloud applications, or at the edge. This step will download and install ThingWorx Kepware Server. Download the ThingWorx Kepware Server executable installer. Right-click on the installer and select Run as administrator. Click Yes in the pop-up asking if you want to proceed. Select your Language and click OK.     On the "Welcome" screen, click Next.     Accept the End-User License Agreement and click Next.     Set the destination folder for the installation and click Next.     Set the Application Data Folder location and click Next. Note that it is recommended NOT to change this path.     Select whether or not you'd like a Shortcut to be created and click Next.     On the "Vertical Suite Selection" screen, keep the default of Typical and click Next.     On the "Select Features" screen, keep the defaults and click Next.     The "External Dependencies" screen simply lists everything that will be installed; click Next.     On the "Default Application Settings" screen, leave the default of Allow client applications to request data through Dynamic Tag address and click Next.     On the “User Manager Credentials” screen, set a unique strong password for the Administrator account and click Next. Note that skipping setting a password can leave your system less secure and is not recommended in a production environment.     Click Install to being the installation.     Click Finish to exit the installer.       Step 3: Create Industrial Gateway   To make a connection between ThingWorx Kepware Server and ThingWorx Foundation, you must first create a Thing.    In ThingWorx Composer, click Browse. On the left, click Modeling -> Things.     Click + NEW. In the Name field, enter IndConn_Server, including matching capitalization.     If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. In the Base Thing Template field, enter indus, then select the IndustrialGateway Thing template from the sorted list. Click Save.   Step 4: Connect Kepware to ThingWorx   This step will get ThingWorx Kepware Server set-up and connected to ThingWorx Foundation.   Now that you have created an Industrial Gateway Thing, you can configure ThingWorx Kepware Server to connect to ThingWorx Foundation.   Follow the steps to Create an Application Key and note the value. The appKey will be used in the the next step. Open the ThingWorx Kepware Server Configuration Windows application, then right-click on Project.     Select Properties….     In the Property Editor pop-up, click ThingWorx. In the Enable field, select Yes from the drop-down. In the Host field, enter the URL or IP address of your ThingWorx Foundation server, without http:// or https://. Enter the Port number.       In the Application Key field, copy and paste the Application Key you just created. In the Trust self-signed certificates field, select Yes from the drop-down. In the Trust all certificates field, select Yes from the drop-down. In the Disable encryption field, select No from the drop-down if you are using another server that uses TLS - URL begins with https://. Select Yes if you are using a ThingWorx Foundation server without TLS - URL begins with http:// Type IndConn_Server in the Thing Name field, including matching capitalization. If you are connecting with a remote instance of ThingWorx Foundation and you expect any breaks or latency in your connection, enable Store and Forward. Click Apply in the pop-up. Click Ok.   In the ThingWorx Kepware Server Event window at the bottom, you should see a message indicating Connected to ThingWorx.     NOTE: If you do not see the “Connected” message, repeat the steps above, ensuring that all information is correct. In particular, check the Host, Port, and Thing name fields for errors.     Step 5: Connect OPC UA Server to Kepware   Now that you have created an Industrial Gateway Thing, and ThingWorx Kepware Server is connected to ThingWorx Foundation, we can connect an OPC UA server to Kepware   Follow the steps to create an OPC UA server in Azure. Enter Resource Group, click Review + create.     Click Create.     In about a minute, the deployment success screen will be displayed.     Click Go to resource, and copy FQDN.     Open ThingWorx Kepware Server Configuration.     Right-click, then click New Channel. Scroll down to select OPC UA Client, then click Next.     Click Next twice to accept default settings, then enter the FQDN copied earlier. Add :50000 to the end of the domain name.     Click Next to accept all defaults. Click Yes to trust the certificate.   Click here to view Part 2 of this guide.
View full tip
    Step 4: Create and Implement State Definitions   A state definition is a collection of style definitions, along with rules for when to apply each style definition. The rule plus the style definition is a state.   In the HelloWorldPlayground Mashup, if the Gauge Widget goes to 10 and the Increment the Count button is clicked once again, the Gauge starts back at 0. This value change is displayed in the Line Chart when it is refreshed. Nevertheless, it would be helpful to have a way to show a user that they’re encroaching 10 and will have to restart, such as the Gauge changing colors in the section. This and many other uses is where State Definitions become useful and go hand and hand with Style Definitions.     Create Style Definition to Represent State Change   First, let’s create Style Definitions to represent the changes in the count. The default Style Definition for a Gauge is the DefaultGaugeFaceStyle Style Definition. We can simply duplicate and update the new Style Definition for our own purposes.   Filter and click the checkbox next to the DefaultGaugeFaceStyle Style Definition. Click Duplicate.   Name the Style Definition UpdatedGaugeFaceStyle. Click Style Information.   Set the Display String property as AlarmingCount. Change the Background Color to light red (color code #D60000 is used in this example).   Change the Secondary Background Color to a darker red (color code #960A0A is used in this example). The inside line of the Gauge Widget is very thin. As an additional exercise, update the Line Thickness property and/or Line Color to see the effect.     Configure State Definition   Now let’s create a State Definition that will use both the default Gauge Style Definition and the one we just created.   In the ThingWorx Composer, click the + New at the top of the screen.   Select State Definitions in the dropdown.   Set the Project (ie, PTCDefaultProject). Name the State Definition GaugeCount. Click States Information.   Set the Apply States dropdown to Numeric.   Set the following values for the default state: Property Value Operator Less than (<) Value 10 Display Name Under 10 Style DefaultGaugeFaceStyle 8. Click the Add State button to create the other states to match the below image:   9. Click Save.   You’ve now created a State Definition. If the value is below 10, the default Gauge format will be applied. Once the value reaches 10, notice the state-based changes you defined are displayed in the appearance of the Gauge.     Implement State Definition in Mashup   Update HelloWorldPlayground Mashup to incorporate the State-based formatting.   Select the Gauge Widget in the Workspace pane and click the ValueFormatter property.   Select the State-based Formatting radio button. Choose Count_Property for the Dependent Field drop-down and select the GaugeCount State Definition that we just created.   Click Done and Save the Mashup. Click View Mashup. If you used the color schemes mentioned, your new HelloWorldPlayground Mashup should look like this.   Click the Increment the Count button to see the state changes. The Gauge now displays a visual indication for when the count is approaching 10.     Enhance State Definition   To further enhance the user experience, you could add another color that warns the user in advance before the threshold is reached. For this example, we will update our State Definition and create a Style Definition that uses the color yellow.   Duplicate the UpdatedGaugeFaceStyle Style Definition.   Name the Style Definition UpdatedGaugeFaceStyle2. Click Style Information.   Set the Display String property to AlarmingYellowCount. Set the Background Color property to yellow (color code #F9EF6B is used in this example).    Set the Secondary Background Color property to a darker yellow (color code #D2CD0E is used in this example). Open the States Information tab of the GaugeCount State Definition. Update the State Definition to fit the image below and utilize the Style Definition we just created: Click Save and View Mashup to see the updated runtime appearance of the application.       Step 5: Implementing Event-Based State Changes   The State and Style Definition you just implemented enables the Gauge to show users when the data property value is approaching the defined threshold. To increase the effectiveness of your application, you can define Event Handling processes that alert the user. In this section we will explain two ways to handle the Event when the count is nearing the threshold value. One, with a Service that gets called whenever the Button Widget is clicked, and the other by using Expression Widgets.   Using a Service to Handle Events In this part of the exercise, we will configure the Mashup so that once the Count hits 9, we will display a more drastically changed Gauge.   Adding Data Service   The below sections are based on the HelloWorldPlayground Mashup.   Select the Gauge Widget in the Workspace pane. Click the Copy button in the toolbar.   Select the Container in the Workspace pane. Click the Paste button in the toolbar. If you Gauge Widgets will not go on top of one another, set the Z-index value of the new Gauge to a smaller number and set the Container Layout Position to static.   Click the green Add Service button in the Data tab next to Things_Hello_World_Thing1 to add two services from you Things_Hello_World_Thing1 Entity. NOTE: You just copied and pasted a Widget inside of a Mashup. While the Mashup retains the same property configurations and style definitions, the pasted Gauge will not have the same connections as the original Widget. You still need to define the inputs/outputs. For this new Gauge, we will only need to connect to the GetPropertyValues service. 6. Add the UnderWarningValue and WarningValueReached Services with the Execute on Load checked for both. 7. Click Done.   Binding Data and Event   With the original Gauge selected, scroll to the Visible property value. Drag and drop the UnderWarningValue service result to the Visible property.   With the new Gauge selected, scroll to the Visible property value. Drag and drop the WarningValueReached service result to the Visible property.   Select the Button Widget in the Workspace pane. Drag and drop the Clicked Event to the UnderWarningValue and WarningValueReached services.   This will ensure the other Services are run whenever the Increment the Count button is clicked.   The UnderWarningValue service will return true if the Count property is under 9. The WarningValueReached service will return true if the Count property is equal to or above 9. The result sent to the original Gauge controls whether the Gauge is visible to users or not.   You could choose to implement a pop-up, alert, or another visual indicator to the UI that would inform your application users. 7. Select the new Gauge in the Mashup or Explorer pane. 8. Clear the GaugeFaceStyle Style Definition and replace it with the DefaultChartStyle11.   9. Click Save and View Mashup to see the changes. Using Expression Widgets to Handle Events   Expression Widgets are a great asset to handle information being passed around inside of a Mashup and also events occurring within a Mashup. In this scenario, we will use the Count property value to create changes in the UI.   Setup Expression Widget   In the Functions Tab in the bottom right. Add a new function.   Set the Function Type to Expression and name it HighCount.   Click Next Click Add Parameter and add a Count (Number) parameter. Set the Expression property to output = Count >= 9;.   Check the Auto Evaluate and Fire on First Value checkboxes. Click Done.     Bind and Evaluate Event   In the Functions Tab in the bottom right, click the bind button of our new Function.   Click the dropdown by the Count input parameter. Click Add Source.   Select Data, then the Count_Property from the GetPropertyValues service.   Redo the past steps for a second Function. Name this function GaugeVisibility with a parameter of type Boolean with the name Visibility. Update the second Expression Widget’s Expression property to output = Visibility != true;. Ensure the checkboxes are checked and bind to the output of our last Function.   Connect the output of this Function to the second Gauge. Click Save and View Mashup.   NOTE: Move the Gauges from on top of one another if necessary to set values and parameters. The first Expression will show the newest Gauge Widget when Count hits 9. The other Expression Widget will show the original Gauge based on the evaluation of the first Expression Widget results.   Click the Increment the Count button to see how the display changes in the Mashup at runtime.   Step 6: Next Steps   The next guide in the Customize UI and Display Options to Deploy Applications learning path is Object-Oriented UI Design Tips.    Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Style & Themes Help Center  
View full tip
  Convey information about IoT data effectively by customizing style definitions and implementing event-based logic   Guide Concept   This project will help you identify how you would like to create an experience for Users.   Following the steps in this guide, you will use color schemes to convey information quickly and effectively, for example to alert users of critical events. With ThingWorx Composer, you can implement Styles and States in your Mashups to enhance your user experience.   We will teach you how to create an affective IoT application experience that looks great and easy to navigate. How the UI is presented can influence users and their enjoyment of the application.   You'll learn how to   Create a Style Definition Customize Style Definitions Create and implement State Definitions Implement event-based state changes   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 60 minutes       Step 1: Completed Example   Download the StylesAndStates.xml attached to this guide.  Within this file, you will find Entities referenced in this lesson, including a finished application.  Import and utilize this file to see a finished example and return to it as a reference if you become stuck during this guide and need some extra help or clarification.   Keep in mind, this download uses the exact names for entities used in this tutorial. If you would like to import this example and also create entities on your own, change the names of the entities you create.     Step 2: Create Style Definition   A Style Definition is a collection of HTML styling elements that can be applied to a Widget just as you would apply a CSS definition to an HTML tag. With Style Definitions, you can control the look and feel, such as colors, fonts, and color context of individual Widgets in your Mashup.   In the ThingWorx Composer, click the + New at the top of the screen.   Select Style Definition in the dropdown.   Enter a name for the Style Definition, such as StyleDefinition. Set the Project to an existing Project (ie, PTCDefaultProject).   Click Style Information.   The Style Information page shows the options for images, colors, lines, and display text. See the table below for information on what each field controls.   6. Type PlaygroundBackground in the Display String field.   NOTE: If you go back to the HelloWorldPlayground, clear the Mashup Style property, then search for StyleDefinition again, you will see the PlaygroundBackground descriptive text.   7. Select Background Color. A color pallet will appear. Select White and click Select.   8. Select Text Color. A color pallet will appear. Select Black and click Select.   9. Click Save.     You have now created your first Style Definition. To ensure a consistent user experience, we recommend creating a Style Definition that you can use throughout your application.    Option                                    Description Display String Descriptive string that can be displayed to indicate the current applied style definition Background Color Background for charts, buttons, panels, etc Secondary Background Color Meant for widgets that support gradients Foreground Color Used for foreground characteristics such as button text and label text Font Bold For text, whether the text should be bold or not Font Italic For text, whether the text should be italicized or not Font Underline For text, whether the text should be underlined or not Image Add images Line Color Pen styling in charts Line Thickness Pen styling in charts Line Style Generally refers to borders. ThingWorx provides the following options: Solid, Dashed, Dotted, None Text Size Choose a font size from 9-72px   In the next part of this exercise, you’ll learn how to use Style Definitions to create an engaging experience for your application users.       Step 3: Customize Style Definitions   Open the HelloWorldPlayground Mashup in Composer, and click View Mashup.   It shows a Button that sends an Event to a Gauge Widget, which then updates a Line Chart.     Modify Style Definition   In this part of the lesson, we'll make some changes to this Mashup. We will use Style Definitions to change the background of the Mashup, change the colors used in the Line Chart in order information stand out, and add color to the Gauge Widget.   In the Explorer tab, select the Mashup. Select the Style Properties tab, then click the X button to clear the Style Mashup Properties.   When editing a Mashup, you can either use a Style Definition Thing that you created earlier OR you can click the wand in a style property for a Mashup or Widget followed by clicking the + Custom button to create a one-time-use style. 3. With the Style Property clear, enter the Style Definition you created in the last section. Update the Background Color to #FF9082 to have the color pop in the Mashup.   4. Click Save and View Mashup to see the changes. You have now updated the background for the HelloWorldPlayground. The style properties you define in the Style Definition will be consitent for any Mashup that references this Style Definition. Change the style around or create a custom style and see the changes in the Mashup. Below is what we'll be working to create. Get ideas of things you might want to see differently in your styling.     Customize Widget Style   ThingWorx provides a default Style Definition for many of its Widgets. Before editing the Style Definitions of a Widget, click the Style Definition property then click View. This enables you to see what the current values are and what you might want to change. If the changes are slight, create a copy of the original Style Definition and update the new version.   Until you are sure of the color schemes you would like to implement, use the default Style Definitions as a guide when creating your own versions.   Default Style Definitions   Next, we will update the colors and style of the Line Chart.   Open the HelloWorldPlayground and select the Line Chart in the Workspace pane. Click the Style Properties tab to see the chart styles section.   Update the Legend->Color property to Blue.     Customize Chart Style Theme   In this part of the lesson, we will update the Series1 and StyleTheme properties of the Line Chart. This is how you'll also set the colors for the chart titles.   The Series1 property will update the look and feel of the line for the count value being used. The Line Chart is a line graph, thus the only property you need to change is the Line Color property.   The StyleTheme property will update the background look of the Line Chart grid.   Clear the StyleTheme and click the + button to create a new theme. Create a theme with the name CustomTheme.   Click the Style tab and edit the feel of the items as you see fit.   After open the Style Theme to be editable, click on colors. Here you'll see all the options and fields that you can make up your own color options and be as conservative as you like or as free as you like.     Click Text Colors, then click on the Grids and Lists tab on the right. This is where we will be shaping our colors for the chart. When you're done with this, update the Core Colors section to make your mashup pop even more.     You may also notice a more focused method of updating grids and lists. In the below Elements section, you'll have a more focused experience for updated.     NOTE: As an extension, after completing the previous steps, try to use Style Definitions to customize the sections of the UI on your own.     Click here to view Part 2 of this guide.
View full tip
    Send data from an MXChip Developer kit to your Azure IoT Hub   GUIDE CONCEPT   Users of the MXChip IoT DevKit (a.k.a. MXChip), follow these quick steps to send temperature and humidity data from built-in IoT DevKit sensors to the Azure IoT Hub.   YOU'LL LEARN HOW TO   Connect the IoT DevKit to a wireless access point Create an Azure IoT Hub and register a device for the IoT DevKit Connect IoT Devkit to Azure IoT Hub   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 80 minutes   Step 1: Create an Azure IoT Hub   Choose +Create a resource, then choose Internet of Things. Click Iot Hub from the list on the right. You see the first screen for creating an IoT hub.   Fill in the fields.   Subscription: Select the subscription to use for your IoT hub.   Resource Group: You can create a new resource group or use an existing one. To create a new one, click Create new and fill in the name you want to use. To use an existing resource group, click Use existing and select the resource group from the dropdown list.   Region: This is the region in which you want your hub to be located. Select the location closest to you from the dropdown list.   IoT Hub Name: Put in the name for your IoT Hub. This name must be globally unique. If the name you enter is available, a green check mark appears.         3. Click Next: Size and scale to continue creating your IoT hub.     On this screen, you can take the defaults and just click Review + create at the bottom.   Pricing and scale tier: You can choose from several tiers depending on how many features you want and how many messages you send through your solution per day. The free tier is intended for testing and evaluation. It allows 500 devices to be connected to the IoT hub and up to 8,000 messages per day. Each Azure subscription can create one IoT Hub in the free tier.   IoT Hub units: The number of messages allowed per unit per day depends on your hub’s pricing tier. For example, if you want the IoT hub to support ingress of 700,000 messages, you choose two S1 tier units.   Advanced / Device-to-cloud partitions: This property relates the device-to-cloud messages to the number of simultaneous readers of the messages. Most IoT hubs only need four partitions.               4. Click Review + create to review your choices. You see something similar to this screen.           5. Click Create to create your new IoT hub. Creating the hub takes a few minutes.     Step 2: Create IoT device   Navigate to the IoT Hub created and in the IoT Devices page, click + New.   2. Enter the device ID used by the demo MXChip application MyNodeDevice. Use the default settings for auto-generating authentication keys and connecting the new device to your hub. Click Save.   3. Navigate to the device created and make a note of the device connection string, which looks like: HostName={YourIoTHubName}.azure-devices.net;DeviceId=MyNodeDevice;SharedAccessKey={YourSharedAccessKey}.   Create Azure Storage   The ThingWorx Azure IoT Connector we will install in the next guide requires an Azure Storage Account. Follow the Microsoft documentation to create an Azure Storage account. NOTE: Select Blob storage as the account type and the Hot Access Tier.     Step 3: Connect to Azure IoT Hub   Download the latest version of GetStarted firmware for IoT DevKit. Connect IoT DevKit to your computer via USB. In Windows you see a new USB mass storage device in Windows Explorer called AZ3166. Drag and drop the .bin file you downloaded from step 1 into the disk named AZ3166 and wait for IoT Devkit to restart. Internet connectivity is required to connect to Azure IoT Hub. Use AP Mode on the DevKit to configure and connect to Wi-Fi.Hold down button B, push and release the Reset button, and then release button B. Your IoT DevKit enters AP mode for configuring the Wi-Fi connection. The screen displays the service set identifier (SSID) of the DevKit and the configuration portal IP address:     5. Use a Web browser on a different Wi-Fi enabled device (computer or mobile phone) to connect to the IoT DevKit SSID displayed in the previous step. If it asks for a password, leave it empty.     6. Open 192.168.0.1 in the browser. Select or input the Wi-Fi network that you want the IoT DevKit to connect to, type the password for the Wi-Fi conection and input the device connection string you made notge of in step 1. Then click Connect.     7. The WiFi credentials and device connection string will be saved in the IoT DevKit even after power cycliong. The following page will be displayed in the browser:     8. The IoT DevKit reboots in a few seconds. You then see the assigned Wi-Fi IP address on the screen of the IoT DevKit:     9. Wait for the IoT DevKit to connect to Azure IoT Hub and you will see it sending telemetry data including temperature and humidity value to Azure IoT Hub. The screen of the IoT Devkit would show message count and temperature/humidity data.       Step 4: Next Steps   Congratulations! You've successfully completed the Connect MXChip to Azure IoT guide. By following the steps in this lesson, you created an Azure IoT Hub and device.     The next guide in the Azure MXChip Development Kit learning path is Create an Application Key.   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Analyze Build a Predictive Analytics Model Build Get Started with ThingWorx for IoT   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Azure Support Page    
View full tip
    Use Thing Shapes to create groups of related Properties   Guide Concept   Save time and effort by modeling a solution in ThingWorx using Thing Shapes to group Properties. A logical group of Properties can be applied to Things and Thing Templates.     You'll learn how to   Create a Thing Shape Add Properties to a Thing Shape   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes       Step 1: Create Thing Shape   In this section you will create a Thing Shape for sensor properties of a MXChip development board.   Thing Shapes are components that contain Properties and Services. In Java programming terms, they are similar to an interface.   Start on the Browse folder icon of ThingWorx Composer. Under the Modeling section of the left-hand navigation panel hover over Thing Shapes, then click the + button.   Type ThermostatShape in the Name field.   If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. Click Save.     Step 2: Add Properties to Thing Shape   Click Properties and Alerts tab at the top of your Thing Shape.   Click + Add. Enter the Property name in the Name field as shown in the table below. Name Base     Type           Persistent?       Logged? humidity NUMBER   X messageId STRING X   temperature NUMBER   X Select the appropriate Base Type from the drop-down menu.   Check Persistent and/or Logged according to the table. NOTE: When Persistent is selected, the property value will be retained during a system restart. Properties that are not persisted will be reset to the default during a system restart. When Logged is selected, every property value change will be automatically logged to a specified Value Stream. Click Check +. TIP: When adding multiple properties at once, click Done and Add after each, once you've entered a Name, selected a Base Type and any other criteria. If adding a single property, click Done. Repeat steps 4 through 6 for each of the properties in the rows of the table. Click the done Check. You'll see that these Properties have been created for the ThermostatShape.   Click Save.     Step 3: Next Steps   Congratulations! You've successfully completed the Create A Thing Shape, and learned how to: Create a new Thing Shape Add Properties to the Thing Shape   This is the last guide in the Azure MXChip Development Kit Learning Path.  If you wish to return to the Learning Path, click the link.   Learn More   The following resources continue your learning experience:  Resource       Link Build Data Model Introduction Experience Object-Oriented UI Design Tips   Additional Resources   If you have questions, issues, or need additional information, refer to:  Resource       Link Community Developer Community Forum Support Thing Shape Support Help Center      
View full tip
  A series of training videos for ThingWorx Analytics   Guide Concept   This guide provides a series of training videos covering ThingWorx Analytics Server and Platform Analytics.   It is recommended that they be viewed in order.    Additionally, a downloadable .zip with additional training materials is provided.     You'll learn how to   Use ThingWorx Analytics Understand the Analytics Thought Process Basic Analytics concepts (data types, variables, modeling) Descriptive Analytics Predictive Analytics modeling techniques Familiarity with other topics: Prescriptive Analytics, Clustering, Time Series, Anomaly Detection Acquire basic knowledge of how to create an end-to-end Smart Application Deepen your Foundation and Analytics understanding NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete all parts of this guide is 12 hours       ThingWorx Analytics Overview   This guide will present a series of training videos for ThingWorx Analytics.It is recommended that you view each guide in-order, as future videos may build on the concepts learned in earlier ones.    Download CourseFiles.zip included in this guide, as it contains important materials for particular videos.   In this course, you will learn the basics of the ThingWorx Analytics Machine Learning process. You will understand how to perform Descriptive Analytics such as identifying Signals, Profiles, or building Clusters.   You will also understand how to train a Model and use Predictive and Prescriptive Scoring. Additional topics include Time Series, Anomaly Detection, and near-real-time Scoring. You will also learn about how to create a simple smart application using Analytics together with other pieces of the overall ThingWorx platform.     ThingWorx Analytics Video Guide   Module 1: ThingWorx Analytics Overview Module 2: Use Case Discussion Module 3: Data Profiling Module 4: Data Transformation and Feature Engineering Module 5: Descriptive Analytics Module 6: Predictive Models and Model Validation Module 7: Scoring Predictive Realtime Prescriptive Module 8: Time Series Modeling Module 9: Anomaly Detection Module 10: ThingWorx Foundation and Analytics Integration Module 11: Mini Project     Next Steps   Congratulations! You've successfully completed the Analytics Training Videos guide, and learned how to:   Use ThingWorx Analytics Understand the Analytics Thought Process Basic Analytics concepts (data types, variables, modeling) Descriptive Analytics Predictive Analytics modeling techniques Familiarity with other topics: Prescriptive Analytics, Clustering, Time Series, Anomaly Detection Acquire basic knowledge of how to create an end-to-end Smart Application Deepen your Foundation and Analytics understanding   Additional Resources If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Analytics Support Help Center          
View full tip
    Step 10: Building and Importing   After you’ve completed your code updates, it’s time to build and import! Below are instructions for building with the framework you have set for the project.   Build Extension with Ant   Go to the Package explorer view. Right click on build-extension.xml. Hover over Run As and select Ant Build.   Your console output will indicate BUILD SUCCESSFUL. This will build your project and create the extension zip in the your_project->build->distributions folder of your 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.   Your console window will display BUILD SUCCESSFUL. Your extension has been created and stored as a zip file in your_project->build->distributions folder.     Import Extension   Go to ThingWorx Composer. In the lower left, click Import/Export, then select Import under.   Select Extension for the type of import.   Choose the zip file in the distributions folder under the build directory. Click Import. Click Close on the prompt to refresh your Composer instance.   After you have imported your new widget and refreshed Composer, you will see your new widget as an option on the Mashup Design tab.     Step 11: Tips   When a new version of an extension contains model changes for one or more of its entities, the previous version of the extension and any entities created from that extension must be deleted before installing the new version of the extension. To avoid having to recreate the entities after the new extension is installed, you can include an extension migrator with the extension that imports the entities created with the previous version.   Adding an Extension Migrator   To create a migrator class for your extensions, follow these steps: Choose the ThingWorx menu and select New Extension Migrator. Select or enter your source folder and package. Enter a name, such as CustomMigrator. Click Finish. The Java source file is created and the configfiles/metadata.xml file is updated automatically.   NOTE: If a migrator has already been created, the previous migrator class name will be replaced in the metadata.xml file with the new migrator class name. The previous migrator Java file will not be changed.   Element Selection   Use this.jqElement to limit your element selections. This will reduce the chance of introducing unwanted behaviors in the application when there might be duplicate IDs and/or classes in the DOM.   ///Don’t do the following: $('.add- btn').click(function(e){...do something...}); ///Do this: this.jqElement.find('.add-btn').click(function(e){ ...do something...});   Logging   We recommend that you use the following methods to log in the Mashup Builder and runtime environment: TW.log.trace(message[,message2,...][,exception]) TW.log.debug(message[,message2,...][,exception]) TW.log.info(message[,message2,...][,exception]) TW.log.warn(message[,message2,...][,exception]) TW.log.error(message[,message2,...][,exception]) TW.log.fatal(message[,message2,...][,exception])   You can view the log messages in the Mashup Builder by opening the log window via the Help->Log menu item; in the Mashup runtime, you can now click on the Show Log button on the top left corner of the page to show log window. If the browser you use supports console.log(), then the messages will also appear in the debugger console.   Formatting   If you have a property with baseType of STYLEDEFINITION, you can get the style information by calling: var formatResult = TW.getStyleFromStyleDefinition( widgetProperties['PropertyName']);   If you have a property of baseType of STATEFORMATTING: var formatResult = TW.getStyleFromStateFormatting({ DataRow: row, StateFormatting: thisWidget.properties['PropertyName'] });   In both cases formatResult is an object with the following defaults: { image: '', backgroundColor: '', foregroundColor: '', fontEmphasisBold: false, fontEmphasisItalic: false, fontEmphasisUnderline: false, displayString: '', lineThickness: 1, lineStyle: 'solid', lineColor: '', secondaryBackgroundColor: '', textSize: 'normal' };     Step 12: Next Steps   Congratulations! You've successfully completed the Create A Mashup Widget Extension tutorial.   You've learned how to:   Utilize the Eclipse Plugin and Extension SDK Create and configure an Extension project Create a mashup widget Extension Build and import an Extension   Learn More   We recommend the following resources to continue your learning experience:    Capability    Guide Build Application Development Tips & Tricks   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource         Link Community Developer Community Forum Help Center  Custom Widget Tips and Example    
View full tip
    Step 7: Widget Lifecycle at Runtime   When a Widget is first created, the runtime will obtain any declared Properties by calling the runtimeProperties() function.   The property values that were saved in the Mashup definition will be loaded into your object without your code being called in any way. After the Widget is loaded but before it’s displayed on the screen, the runtime will call renderHtml() for you to return the HTML for your object. The runtime will render that HTML into the appropriate place in the DOM. Immediately after that HTML is added to the DOM, you will be called with afterRender(). This is the time to do the various jQuery bindings (if you need any). It is only at this point that you can reference the actual DOM elements, and you should only do this using code such as:   // note that this is a jQuery object var widgetElement = this.domElement;   This is important because the runtime actually changes your DOM element ID (domElementId) and you should never rely on any ID other than the ID returned from this.   If you have defined an event that can be bound, whenever that event occurs, you should call the following:   var widgetElement = this.domElement; // change ‘Clicked’ to be whatever your event name is that // you defined in your runtimeProperties that people bind to widgetElement.triggerHandler('Clicked'); 4. If you have any properties bound as data targets, you will be called with updateProperty(). You are expected to update the DOM directly if the changed property affects the DOM - this is likely, otherwise why would the data be bound. 5. If you have properties that are defined as data sources and they are bound, you can be called with getProperty_{propertyName}() …. If you don’t define this function, the runtime will simply get the value from the property bag.     Step 8: Runtime APIs available to Widgets   The following APIs can be accessed by a Widget in the context of the runtime:   this.jqElementId - This is the DOM element ID of your object after renderHtml(). this.jqElement - This is the jquery element. this.getProperty(name) - Accessor. this.setProperty(name,value) - Modifier. this.updateSelection(propertyName, selectedRowIndices) - Call this anytime your Widget changes selected rows on data that is bound to a certain propertyName. For example, in a callback for an event like onSelectStateChanged(), you would call this API and the system will update any other Widgets relying on selected rows.   Step 9: Runtime Callbacks   The following functions on the widget are called by the runtime.   runtimeProperties() - [optional] Returns a JSON structure defining the properties of this widget. Optional properties are:   isContainer - true or false (default to false); Controls whether an instance of this widget can be a container for other widget instances. needsDataLoadingAndError - true or false (defaults to false) - Set to true if you want your widget to display the standard 25% opacity when no data has been received and to turn red when there is an error retrieving data. borderWidth - If your widget provides a border, set this to the width of the border. This helps ensure pixel-perfect WYSIWG between builder and runtime. supportsAutoResize- If your widget supports auto-resize, set this to true. propertyAttributes – If you have STRING properties that are localizable, list them here. For example, if TooltipLabel1 is localizable:   this.runtimeProperties = function () { return { 'needsDataLoadingAndError': true, 'propertyAttributes': { 'TooltipLabel1': {'isLocalizable': true} } } };   renderHtml() [required] - Returns HTML fragment that runtime will place on the screen; the widget’s content container (e.g. div) must have a ‘widget- content’ class specified. After this container element is appended to the DOM, it becomes accessible via jqElement and its DOM element ID will be available in jqElementId. afterRender() [optional] - Called after the widget HTML fragment is inserted into the DOM. Use this domElementId to find the DOM element ID. Use this jqElement to use the jQuery reference to this DOM element. beforeDestroy() [optional but highly recommended] - This is called anytime the widget is unloaded. This is where to:   unbind any bindings clear any data set with .data() destroy any third-party libraries or plugins, call their destructors, etc. free any memory you allocated or are holding onto in closures by setting the variables to null There is no need to destroy the DOM elements inside the widget, they will be destroyed for you by the runtime. resize(width,height) [optional – Only useful if you declare supportsAutoResize: true] - This is called anytime the widget is resized. Some widgets don’t need to handle this, for example, if the widget’s elements and CSS auto-scale. But others (most widgets) need to actually do something to accommodate the widget changing size. handleSelectionUpdate(propertyName, selectedRows, selectedRowIndices) - Called whenever selectedRows has been modified by the data source you’re bound to on that PropertyName. selectedRows is an array of the actual data and selectedRowIndices is an array of the indices of the selected rows. Note: To get the full selectedRows event functionality without having to bind a list or grid widget, this function must be defined.   serviceInvoked(serviceName)- serviceInvoked() - Called whenever a service you defined is triggered. updateProperty(updatePropertyInfo) - updatePropertyInfo An object with the following JSON structure:   { DataShape: metadata for the rows returned ActualDataRows: actual Data Rows SourceProperty: SourceProperty TargetProperty: TargetProperty RawSinglePropertyValue: value of SourceProperty in the first row of ActualDataRows SinglePropertyValue: value of SourceProperty in the first row of ActualDataRows converted to the defined baseType of the target property [not implemented yet], SelectedRowIndices: an array of selected row indices IsBoundToSelectedRows: a Boolean letting you know if this is bound to SelectedRows }   For each data binding, the widget’s updateProperty() will be called every time the source data is changed. You need to check updatePropertyInfo. TargetProperty to determine what aspect of the widget needs to be updated. An example from thingworx.widget.image.js:   this.updateProperty = function (updatePropertyInfo) { // get the img inside our widget in the DOM var widgetElement = this.jqElement.find('img'); // if we're bound to a field in selected rows // and there are no selected rows, we'd overwrite the // default value if we didn't check here if (updatePropertyInfo.RawSinglePropertyValue !== undefined) { // see which TargetProperty is updated if (updatePropertyInfo.TargetProperty === 'sourceurl') { // SourceUrl updated - update the <img src=this.setProperty('sourceurl', updatePropertyInfo.SinglePropertyValue); widgetElement.attr("src", updatePropertyInfo.SinglePropertyValue); } else if (updatePropertyInfo.TargetProperty === 'alternatetext') { // AlternateText updated - update the <img alt= this.setProperty('alternatetext', updatePropertyInfo.SinglePropertyValue); widgetElement.attr("alt", updatePropertyInfo.SinglePropertyValue); } } };   NOTE: In the code above, we set a local copy of the property in our widget object, so if that property is bound as a data source for a parameter to a service call (or any other binding) - the runtime system can simply get the property from the property bag. Alternately, we could supply a custom getProperty_ {propertyName} method and store the value some other way.   getProperty_{propertyName}() - Anytime that the runtime needs a property value, it checks to see if the widget implements a function that overrides and gets the value of that property. This is used when the runtime is pulling data from the widget to populate parameters for a service call.     Click here to view Part 4 of this guide.
View full tip
  Step 5: Mashup Builder API   The following APIs can be accessed by a widget in the context of the Mashup Builder:    API                                                                                                                Description this.jqElementId This is the DOM element ID of your object after renderHtml(). this.jqElement This is the jquery element. this.getProperty(name) / this.setProperty(name,value) Note that every call to this function will call afterSetProperty() if it’s defined in the widget. this.updatedProperties() This function should be called anytime properties are changed in the widget so that the Mashup Builder can update the widget properties window, the connections window, and so on. this.getInfotableMetadataForProperty(propertyName) If you need the infotable metadata for a property that you bound, you can get it by calling this API; it returns undefined if it is not bound. this.resetPropertyToDefaultValue(propertyName) This call resets the named property to its default value. this.removeBindingsFromPropertyAsTarget(propertyName) This call removes target data bindings from the propertyName. Use it only when the user has initiated an action that invalidates the property. this.removeBindingsFromPropertyAsSource(propertyName) This call removes source data bindings from the propertyName. Use this only when the user has initiated an action that invalidates the property. this.isPropertyBoundAsTarget(propertyName) This call returns a result that indicates if the property has been bound as a target. You can use it to determine if a property has been set or bound. this.isPropertyBoundAsSource(propertyName) This call returns a result that indicates if the property has been bound as a source. You can use it to determine if a property has been bound to a target.   Example of the Checkbox Widget’s validate() function: this.validate = function () { var result = []; if (!this.isPropertyBoundAsSource('State') && !this.isPropertyBoundAsTarget('State')) { result.push({ severity: 'warning', message: 'State for {target-id} is not bound' }); } return result; }   Example of the Blog Widgets validate() function: this.validate = function () { var result = []; var blogNameConfigured = this.getProperty('Blog'); if (blogNameConfigured === '' || blogNameConfigured === undefined) { if (!this.isPropertyBoundAsTarget('Blog')) { result.push({ severity: 'warning', message: 'Blog is not bound for {target-id}' }); } } return result; }     Step 6: Mashup Builder Callbacks   The following widget functions are called by the Mashup Builder to control the widget’s behavior. widgetProperties() - Returns a JSON structure that defines the properties of the widget. Listed are the possible properties of the widget:   Required Property   The only required property is:   name - The user-friendly widget name, as shown in the widget toolbar   Optional Properties   There are a number of optional properties that can be contained in the returned JSON structure.    Property                                                                 Description description A description of the widget, used for its tooltip. iconImage - File name of the widget icon/image category An array of strings for specifying one or more categories to which the widget belongs (such as “Common”, “Charts”, “Data”, “Containers”, and “Components”), enabling widgets to be filtered by type/category. isResizable true (default) or false defaultBindingTargetProperty Name of the property to use as the data/event binding target borderWidth If the widget has a border, set this property to the width of the border. This property ensures pixel-perfect WYSIWG between design and runtime. If you set a border of one pixel on the widget-content element at design time, you are making the widget two pixels taller and two pixels wider (one pixel on each side). To account for this discrepancy, set the borderWidth property to make the design-time widget the same number of pixels smaller. This property places the border inside the widget that you created and makes the width and height in the widget properties accurate. isContainer true or false (default). Controls whether an instance of the widget can be a container for other widget instances. customEditor The name of the custom editor dialog for entering and editing the widget configuration. The system assumes there is a dialog you created named TW.IDE.Dialogs.<name>. customEditorMenuText The text that appears on the flyout menu of the widget and the tooltip text for the Configure Widget Properties button. For example, “Configure Grid Columns.” allowPositioning true (default) or false supportsLabel true or false (default). If true, the widget exposes a label property used to create a text label that appears next to the widget in the Composer and at runtime. supportsAutoResize true or false (default). If true, the widget can be placed in responsive containers (such as columns, rows, responsive tabs, responsive mashups). properties A collection of JSON objects for the widget that describe the properties of the widget that can be modified when the widget is added to a mashup. These properties are displayed in the Properties window of the Mashup Builder - the name of each object is used as the property name and the corresponding attributes control how the property value is set. afterLoad() Called after the object is loaded and properties have been restored from the file, but before the object has been rendered renderHtml() [required] Returns HTML fragment that the Composer will place in the screen; the widget’s content container (e.g. div) must have a ‘widget-content’ class specified. After this container element is appended to the DOM, it becomes accessible via jqElement and its DOM element ID will be available in jqElementId widgetEvents() A collection of events. warnIfNotBound true or false; If true, the property will be checked by Composer to determine whether it is bound, then generate a to-do item if/when it is not. widgetServices() A collection of services. warnIfNotBound true or false; If true, the property will be checked by the Composer to determine whether it is bound, then generate a to-do item if/when it is not. afterRender() Called after the HTML fragment is inserted into the DOM. beforeDestroy() Called right before the widget’s DOM element gets removed and the widget is detached from its parent widget and delocated; this is the place in which to perform any clean-up of resources (e.g. plugins, event handlers) acquired throughout the lifetime of the widget. beforeSetProperty(name,value) [Mashup Builder only - not at runtime] Called before any property is updated within Composer; this is a good place to perform validation on the new property value before it is committed. If a message string is returned, then the message will be displayed to the user, and the new property value will not be committed. If nothing is returned, then the value is assumed to be valid. afterSetProperty(name,value) [Mashup Builder only - not at runtime] Called after any property is updated within Composer. Return true to have the widget re-rendered in Composer. afterAddBindingSource(bindingInfo) Whenever data is bound to the widget, you will call back with this (if you implemented it … it’s optional). The only field in bindingInfo is targetProperty which is the propertyName that was just bound. validate() Called when Composer refreshes its to-do list. The call must return an array of result objects with severity (optional and not implemented) and message (required) properties. The message text may contain one or more pre-defined tokens, such as {target-id}, which will contain a hyperlink that allows the user to navigate to or select the specific widget that generated the message.   Properties Section Breakdown   The following attributes can be specified for each property object:    Aspect                                           Description description A description of the widget, which is used for its tooltip. baseType The system base type name - if the baseType value is FIELDNAME the widget property window displays a dropdown list of fields available in the INFOTABLE bound to the sourcePropertyName value based on the baseTypeRestriction. mustImplement If the baseType is THINGNAME and you specify “mustImplement”, the Mashup Builder will restrict popups to those implementing the specified EntityType and EntityName [by calling QueryImplementingThings against said EntityType and EntityName]. baseTypeInfotableProperty If baseType is RENDERERWITHFORMAT, baseTypeInfotableProperty specifies which property’s infotable is used for configuration. sourcePropertyName When the property’s baseType is FIELDNAME, this attribute is used to determine which INFOTABLE’s fields are to be used to populate the FIELDNAME dropdown list. baseTypeRestriction When specified, this value is used to restrict the fields available in the FIELDNAME dropdown list. tagType If the baseType is TAGS this can be ‘DataTags’ (default) or ‘ModelTags.’ defaultValue Default undefined; used only for ‘property’ type. isBindingSource true or false; Allows the property to be a data binding source, default to false. isBindingTarget true or false; Allows the property to be a data binding target, default to false. isEditable true or false; Controls whether the property can be edited in Composer, default to true. isVisible true or false; Controls whether the property is visible in the properties window, default to true. isLocalizable true or false; Only important if baseType is STRING - controls whether the property can be localized or not. selectOptions An array of value / (display) text structures. warnIfNotBoundAsSource true or false; If true, the property will be checked by Composer to determine whether it is bound and generate a to-do item if/when it is not. warnIfNotBoundAsTarget true or false; If true, the property will be checked by Composer to determine whether it is bound and generate a to-do item if/when it is not.   Other Special BaseType   Additional special baseTypes:   STATEDEFINITION - Picks a StateDefinition STYLEDEFINITION - Picks a StyleDefinition RENDERERWITHSTATE - Displays a dialog and allows you to select a renderer and formatting. Note: You can set a default style by entering the string with the default style name in the defaultValue. When your binding changes, you should reset it to the default value, as shown in the code below:   this.afterAddBindingSource = function (bindingInfo) { if(bindingInfo['targetProperty'] === 'Data') { this.resetPropertyToDefaultValue('ValueFormat'); } }; STATEFORMATTING - Displays a dialog and allows you to pick a fixed style or state-based style. Note: You can set a default style by entering the string with the default style name in the defaultValue. When your binding changes, you should reset it to the default value as shown in the code above for RENDERERWITHSTATE. VOCABULARYNAME - Will pick a DataTag vocabulary   Some Examples   An example of the properties property: properties: { Prompt: { defaultValue: 'Search for...', baseType: STRING, isLocalizable: true }, Width: { defaultValue: 120 }, Height: { defaultValue: 20, isEditable: false }, }   An example of mustImplement: 'baseType': 'THINGNAME', 'mustImplement': { 'EntityType': 'ThingShapes', 'EntityName': 'Blog' }   An example of selectOptions:[ {value: ‘optionValue1’, text: ‘optionText1’}, {value: ‘optionValue2’, text: ‘optionText2’} ]   An example of validate function that allows you to navigate/select the specific widget that generated the message: this.validate = function () { var result = []; var srcUrl = this.getProperty('SourceURL'); if (srcUrl === '' || srcUrl === undefined) { result.push({ severity: 'warning', message: 'SourceURL is not defined for {target-id}'}); } return result; }     Click here to view Part 3 of this guide.
View full tip
    Step 3: Creating Customer Data   Now let’s begin creating the customer data. Just enough examples for us to understand what is happening at each step. Let’s create at least 4 customers by following the steps below:   Open the Fizos.Customers.DataTable Data Table and go to the services tab. Open the AddDataTableEntries service to be executed. This service will allow us to create some general data to work with. You can create as many as you like for this test. Click the values parameter to start creating entries. After clicking + Add, and enter data for customers. Try to add at least 1 Factor data tag for each customer.     Save your entry and create a second entry with any location and tags you like. We aren’t adding vehicles as of yet, but we will in the next section. After saving, don’t forget to execute the service with the two entries saved. If you did it correctly, the values parameter of the service, should show at least 1 inside of the parentheses. See below for an example:     We just added customers manually. While convenient for our test, what we truly want is a system that is hands off. What we need is, a way to add customers programatically. Whether a customer is ordering on a website you created for them or they are checking out as a guest (we still want to track this). Below, you’ll see a quick service to add a new user. This service can be created inside of the Fizos.Customers.DataTable data table.   var customer = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape({ infoTableName : "InfoTable", dataShapeName : "Fizos.Customers.DataShape" }); var count = me.GetDataTableEntryCount(); var newEntry = {}; newEntry.ID = count + 1; newEntry.UUID = generateGUID(); newEntry.Type = Type; newEntry.Factors = "Fizos.CustomerTags:FirstTime"; newEntry.Name = Name; newEntry.Email = Email; newEntry.Address = Address; newEntry.Phone = Phone; customer.AddRow(); me.AddDataTableEntry({ sourceType: "Service", values: customer, source: "AddNewCustomer" }); We can adapt these for the customers that would rather not have accounts and be considered guests. Instead of the FirstTime data tag, you might want to add a Guest tag. For name, you could have it empty. The other fields, you’ll still want to likely have. This can give you insight into who these customers are that rather the guest checkout/ordering.     Step 4: Expanding Logistics Models   Let's do a quick review of what we have before we jump forward. In this Learning Path, we've setup scheduled factory inspections, machine automation, created customers, and setup order creation. What we're missing is the handling of deliveries.   In this learning path, we have talked about how to handle design aspects that could be held in a data table or have entities created to model each one. While there are many pros and cons to each method, we will do a mixture of both. Having the logistics data in data tables provide us with an easy form of querying data. Having entities match up with vehicles/transportation allows us to have greater tracking and live updates.   Let's create the vehicle/transportation data model, come up with logic on how to do deliveries from the factories we created earlier in this learning path, then setup a schedule or timer to kickstart the process.   Vehicles Data Model We already have our Data Table of vehicles. Let's create the templates and entities that will be a 1 to 1 between Thing and vehicle.   In the ThingWorx Composer, click the + New in the top left of the screen.   Select Thing Shape in the dropdown.   In the name field, enter Fizos.Vehicles.ThingShape and select a Project (ie, PTCDefaultProject). This Entity will have Services implemented by all types of vehicles. Save your changes and create three Thing Templates which implement this Thing Shape. See below for examples:   Fizos.Vans.ThingTemplate: These are smaller vehicles used to make short or last step deliveries.     Fizos.Trucks.ThingTemplate: These are trucks of different types making larger deliveries.     Fizos.Planes.ThingTemplate: These are planes used to deliver products to long distance locations.     Handling Shipping and Deliveries The cost of shipping and delivering goods is often the last thing people want to think about. Sometimes the cost of shipping goods is more expensive than the goods themselves. So how can we make this one of our strongest factors? By continuing trying to make our design simpler and less costly. We all know that it won't be an easy feat. The best way to do this is to have a system where we can have analytics and continuously improve on.   Let's start with the beginner steps of creating our straight-forward delivery service. Then, we will add Value Streams and tracking to see where we can make improvements. Finally, the solutions get better as we repeat these steps. No one solution is perfect, and no logic will be without holes or issues. Nevertheless, you continuously work on it, so that you can save cost and improve customer experience.   Open Fizos.Vehicles.ThingShape and go to the Properties tab. Create the following list of Properties. These properties are the generic concepts for a vehicle that can deliver a package. Name Base Type Aspects Details FuelCapacity Number 0 minimum, unit: liters logged, persistent AverageFuelConsumption Number 0 minimum, unit: liters logged, persistent MaxMass Number 0 minimum, unit: kilograms logged, persistent MaxVolume Number 0 minimum, unit: cubic meters logged, persistent CurrentLocation Location N/A logged, persistent CurrentOrders InfoTable(Fizos.Orders.DataShape) N/A logged, persistent Your properties should look like the following: Inside the Fizos.Vehicles.ThingShape entity, go to the Services tab. Create the following list of Services. These services are also generic in nature and are based on the concept of a vehicle going to a pick up location, goods being loaded onto the vehicle, the vehicle traveling to a destination, then delivering goods. Name Input Return Type Override Async Description PickUpGoods PickUpLocation: Location Nothing Yes Yes Go to a pickup location (factory or otherwise), and pick up goods. LoadGoods Orders: InfoTable (Fizos.Orders.DataShape) Nothing Yes Yes Perform the task of loading goods onto a vehicle (adding rows to the CurrentOrders property) Travel Destination: Location Nothing Yes Yes Travel for destination A to destination B DeliverGoods Orders: InfoTable (Fizos.Orders.DataShape) Nothing Yes Yes Perform the task of unloading goods at a current location As you can see, the goods are orders. In a real world environment, we would create a separate Data Shape and Data Table for packages to hold a number of orders. We are doing this without the packages Data Table for simplicity in this example. One reason why our products have mass and volume properties is to help with the idea of loading a vehicle and the type of boxes or packaging to use. This could be another way to cut cost. Your Services should look like the following: The same way we were able to create a system that was automated, we will create events that will notify subscribers of certain tasks being complete. This way, the next level of service can be performed instantly by our robot army. Inside the Fizos.Vehicles.ThingShape entity, go to the Events tab. Create the following list of events. These Events will connect to a task being completed. For example, when the vehicle has arrived to a location, an Event will be triggered and thus the next task can begin. For a bit more automation, add an Event you might think is needed, like when fuel is needed in the vehicle.   Name Data Shape Description DestinationReached AlertEvent This alert is fired when the vehicle has reached a location (whether for delivery or pickup). OrdersLoaded AlertEvent This alert is fired when all orders have been loaded onto a vehicle. DeliveryCompleted AlertEvent This alert is fired when the vehicle has completed a delivery. This delivery might have been the last order delivery and vehicle needs to head back for more orders to be picked up. Your Services should look like the following: Let's take a quick break to go over how this will work. A Service in the Fizos.Logistics Entity will search for all Things that implement the Fizos.Vehicles.ThingShape Entity. Each list of these Entities will have it's PickUpGoods Service called with the desired pickup location. When the destination is reached inside of the PickUpGoods Service, the DestinationReached Alert will be triggered. A Subscription waiting for this Event at the Thing level, will call the LoadGoods Service based on the condition of no orders being in the vehicle CurrentOrders Property. This LoadGoods Service will finish and trigger a OrdersLoaded Event. A subscription waiting for this Event at the Thing level, will call the Travel service. The Service will be called with the customer location as the destination OR the location of another site to perform other tasks. When the destination is reached inside of the Travel Service, the DestinationReached Alert will be triggered. A Subscription waiting for this Event at the Thing level, will call the DeliverGoods Service based on the condition of orders being left in the CurrentOrders Property. When the delivery is complete, the DeliveryCompleted Alert will be triggered. A Subscription waiting for this Event at the Thing level, will decide whether to go to a factory or pickup location to restart the process or wait for more instructions. You may have noticed a few things here. For starters, we are starting this from the Fizos.Logistics entity instead of a scheduler. For this process, you can start it with a scheduler, but being a 24 hour company, we don't have a schedule to start deliveries. That being said, the click of a button would do the job.   You can also see that we haven't given you the service code for some of these services. For some of these functions, they're almost duplicates of prior services. What will be more challenging and fun is the logic for which orders go to which delivery method. This is a mixture of vehicle properties, order properties, customer type, and customer location.     Step 5: Next Steps   Congratulations! You've successfully completed the Automated Distribution and Logistics guide.   In this guide, you learned how to: Create automated logistical processes Use services, alerts, and subscriptions to handle processes without human interaction Integrating complex logic with straight forward step by step systems   The next guide in the Complex and Automatic Food and Beverage Systems learning path is Securing Industry Data.    Learn More We recommend the following resources to continue your learning experience:   Capability            Guide Build ThingWorx Solutions in Food Industry Build Design Your Data Model Build Implement Services, Events, and Subscriptions   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Help Center
View full tip
  Connect an ESP8266 WiFi module using the Arduino programming environment and the ThingWorx REST API.   This information was created for a previous version of ThingWorx and may not be fully accurate. Report any issues with this article here.   Guide Concept   This project will introduce the utilities ThingWorx provides for connections to an Adafruit Feather.   Following the steps in this guide, you will have a fully configured setup between your Adafruit Feather and the ThingWorx platform to begin your IoT development.   We will teach you how to utilize the ThingWorx REST API and the Arduino programming language to connect your Adafruit Feather for IoT application development.   You'll learn how to   Connect an ESP8266 WiFi module to a ThingWorx server Use the Arduino programming environment with the ThingWorx REST API   NOTE:  The estimated time to complete this guide is 30 minutes.      Step 1: Install Software   Arduino   There are three pieces of software to install before getting started with the ThingWorx-specfic code: Install FTDI USB driver. If you have connected development boards to your PC in the past you probably already have this installed. The latest Arduino IDE full install will also install the driver. NOTE: SparkFun has an excellent FTDI Driver Installation guide.   3. Arduino IDE - version 1.6.4 or later recommended. 4. Install ESP8266 addon into Arduino IDE. 5. The SparkFun Setting Up the Arduino IDE Tutorial is a great guide to getting started with their board. 6. Adafruit also has a great with their board Testing a Wifi Connection Tutorial.   When everything is set-up correctly and you are able to upload and see the Blink demo flashing the LED on the board you are ready to move to the next step.   ThingWorx Foundation Server   Start, and Launch your ThingWorx Foundation server. Log into Composer.  You will need a ThingWorx appKey to authorize the board.  Follow these instructions in Create an Application Key to create an appKey that you will copy into the source code in the next step.       Step 2: Set up Arduino IDE, Developer Board, and ThingWorx Server   Once you are able to run the blink test sketch, your IDE and board are set-up correctly. To learn how to run the blink test, read the SparkFun Board Instructions and the Adafruit board instructions.   Arduino IDE   Before you will be able to run the code below that connects a developement board to a ThingWorx Foundation server, you will need to modify the code with four pieces of information specific to your environment. You will need:   A WiFi access point SSID The correct password for the WiFi access point The IP address or URL of a ThingWorx Foundation Server A valid appKey created by your ThingWorx Foundation Server. To create an appKey, follow these instructions to Create An Application Key   Create a new sketch in the Arduino IDE then copy and paste the code below into the IDE.   Modify the WiFi Definitions and the ThingWorx server definitions shown in the code with your specficic information then save the sketch with a new name. The next step will describe what you should see when you upload and run the code on your developer board.   /** * * ESP8266_ThingWorx_REST_Demo.ino * * * (c) PTC, Inc. 2016-2020 * */ #include <Arduino.h> #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #include <WiFiClientSecureBearSSL.h> ////////////////////// // WiFi Definitions // ////////////////////// const char WiFiSSID[] = "Liberty454"; // WiFi access point SSID const char WiFiPSK[] = "Flutie22"; // WiFi password - empty string for open access points ////////////////////////////////////////////// // ThingWorx server definitions // // modify for a specific platform instance // ////////////////////////////////////////////// const char TWPlatformBaseURL[] = "https://pp-2007011431nt.devportal.ptc.io"; const char appKey[] = "2d4e9440-3e51-452f-a057-b55d45289264"; //////////////////////////////////////////////////////// // Pin Definitions - board specific for Adafruit board// //////////////////////////////////////////////////////// const int RED_LED = 0; // Thing's onboard, red LED - const int BLUE_LED = 2; // Thing's onboard, blue LED const int ANALOG_PIN = A0; // The only analog pin on the Thing const int OFF = HIGH; const int ON = LOW; // this will set as the Accept header for all the HTTP requests to the ThingWorx server // valid values are: application/json, text/xml, text/csv, text/html (default) #define ACCEPT_TYPE "text/csv" ///////////////////// //Attempt to make a WiFi connection. Checks if connection has been made once per second until timeout is reached //returns TRUE if successful or FALSE if timed out ///////////////////// boolean connectToWiFi(int timeout){ Serial.println("Connecting to: " + String(WiFiSSID)); WiFi.begin(WiFiSSID, WiFiPSK); // loop while WiFi is not connected waiting one second between checks uint8_t tries = 0; // counter for how many times we have checked while ((WiFi.status() != WL_CONNECTED) && (tries < timeout) ){ // stop checking if connection has been made OR we have timed out tries++; Serial.printf(".");// print . for progress bar Serial.println(WiFi.status()); delay(2000); } Serial.println("*"); //visual indication that board is connected or timeout if (WiFi.status() == WL_CONNECTED){ //check that WiFi is connected, print status and device IP address before returning Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); return true; } else { //if WiFi is not connected we must have exceeded WiFi connection timeout return false; } } ////////////////////////// //create a name for the board that is probably unique by appending last two bytes of MAC address //return name as a String /////////////////////////////// String getUniqueDeviceName(){ String uniqueName; uint8_t mac[WL_MAC_ADDR_LENGTH]; WiFi.macAddress(mac); // WiFi does NOT need to be connected for this call String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) + String(mac[WL_MAC_ADDR_LENGTH - 1], HEX); macID.toUpperCase(); uniqueName = "ESP8266Board-" + macID; Serial.println("DeviceID>" + uniqueName); return uniqueName; } /////////////////////////////// // make HTTP GET to a specific Thing and Propertry on a ThingWorx server // thingName - Name of Thing on server to make GET from // property - Property of thingName to make GET from // returns HTTP response code from server and prints full response /////////////////////////////// int httpGetPropertry(String thingName, String property){ std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure); client->setInsecure(); HTTPClient https; int httpCode = -1; String response = ""; Serial.print("[httpsGetPropertry] begin..."); String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Things/"+ thingName +"/Properties/"+ property +"?appKey=" + String(appKey); https.begin(*client,fullRequestURL); https.addHeader("Accept",ACCEPT_TYPE,false,false); Serial.println("GET URL>" + fullRequestURL +"<"); // start connection and send HTTP header httpCode = https.GET(); // httpCode will be negative on error if(httpCode > 0) { response = https.getString(); Serial.printf("[httpGetPropertry] response code:%d body>",httpCode); Serial.println(response + "<\n"); } else { Serial.printf("[httpGetPropertry] failed, error: %s\n\n", https.errorToString(httpCode).c_str()); } https.end(); return httpCode; } /////////////////////////////// // makes HTTP POST to platform to CreateThing service using input string as the new Things's name. // Returns server response code /////////////////////////////// int createThing(String nameOfThing){ std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure); client->setInsecure(); HTTPClient https; int httpCode = -1; String response = ""; Serial.print("[createThing] begin..."); String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Resources/EntityServices/Services/CreateThing?appKey=" + String(appKey); https.begin(*client,fullRequestURL); https.addHeader("Accept",ACCEPT_TYPE,false,false); https.addHeader("Content-Type","application/json",false,false); Serial.println("POST URL>" + fullRequestURL + "<"); // start connection and send HTTP header httpCode = https.POST("{\"name\": \""+ nameOfThing +"\",\"thingTemplateName\": \"GenericThing\"}"); // httpCode will be negative on error if(httpCode > 0) { response = https.getString(); Serial.printf("[createThing] response code:%d body>",httpCode); Serial.println(response + "<\n"); } else { Serial.printf("[createThing] POST... failed, error: %s\n\n", https.errorToString(httpCode).c_str()); } https.end(); return httpCode; } /////////////////////////////// // make HTTP POST to ThingWorx server Thing service // nameOfThing - Name of Thing to POST to // endPoint - Services URL to invoke // postBody - Body of POST to send to ThingWorx platform // returns HTTP response code from server /////////////////////////////// int postToThing(String nameOfThing, String endPoint, String postBody){ std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure); client->setInsecure(); HTTPClient https; int httpCode = -1; String response = ""; Serial.print("[postToThing] begin..."); String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Things/"+ nameOfThing +"/Services/"+ endPoint +"?appKey=" + String(appKey); Serial.println("URL>" + fullRequestURL + "<"); https.begin(*client,fullRequestURL); https.addHeader("Accept",ACCEPT_TYPE,false,false); https.addHeader("Content-Type","application/json",false,false); Serial.println("[postToThing] POST body>" + postBody + "<"); // start connection and send HTTP header httpCode = https.POST(postBody); // httpCode will be negative on error if(httpCode > 0) { response = https.getString(); Serial.printf("[postToThing] response code:%d body>",httpCode); Serial.println(response + "<\n"); } else { Serial.printf("[postToThing] POST... failed, error: %s\n\n", https.errorToString(httpCode).c_str()); } https.end(); return httpCode; } void setup() { pinMode(RED_LED, OUTPUT); pinMode(BLUE_LED, OUTPUT); Serial.begin(115200); Serial.setDebugOutput(true); Serial.println(); Serial.println(); Serial.println(); Serial.printf("Starting...\n"); for(uint8_t t = 4; t > 0; t--) { Serial.printf(" WAIT %d...\n", t); Serial.flush(); delay(1000); } connectToWiFi(10); } void loop() { String thingName = getUniqueDeviceName(); //unique name for this Thing so many work on one ThingWorx server while (WiFi.status() == WL_CONNECTED) { //confirm WiFi is connected before looping as long as WiFi is connected int getResponseCode = httpGetPropertry(thingName, "SomeNumber"); if (getResponseCode == 404){ // a 404 means connected, but either no Thing or no property // first we will try to create a new Thing on the platform int postResp = createThing(thingName); // saving the response code for retry logic in the future // the newly crated Thing has to be enabled postResp = postToThing(thingName,"EnableThing",""); //POST to EnableThing endpoint with no body // after the new Thing is enabled it must be restarted postResp = postToThing(thingName,"RestartThing",""); //POST to RestartThing endpoint with no body // add a property to the Thing 3rd parameter is ugly because required quotes are escaped with backslashes postResp = postToThing(thingName,"AddPropertyDefinition", "{\"name\":\"SomeNumber\",\"type\":\"NUMBER\"}"); //POST body contains JSON object with property name and property type // after changes to a Thing's structure it must be restarted postResp = postToThing(thingName,"RestartThing",""); //POST to RestartThing endpoint with no body } delay(2000); }// end WiFi connected while loop Serial.printf("****Wifi connection dropped****\n"); WiFi.disconnect(true); delay(10000); connectToWiFi(10); }     Step 3: Run Arduino Demo   Click on the right arrow in the Arduino IDE toolbar to upload and start the sketch. Note:The compile and upload process will take almost a minute and will show [ 100% ] when it is completed successfully. 2. After the upload is complete, click on Tools > Serial Monitor and select 115200 baud from the drop down in the lower right.            Check Connection on ThingWorx Server   Open the Composer window of your ThingWorx Foundation server and click on the browse folder icon, then Things.   You will see a Thing named "ESP8266Board-XXXX" with XXXX replaced by the last 4 digits of your boards WiFi MAC address. Click on the Thing then click the Properties and Alerts tab in the left column. Click the pencil "Set value" icon in the value column and enter a number in the text box. Click the "Check" button to set the value.   Open the Arduino Serial monitor window, and you will see the value you just entered on the platform shown in the serial output.   Step 4: Next Steps   Congratulations! You've successfully completed the Connect an Arduino Developer Board Quickstart.   This guide has given you the basic tools to:   Set up Arduino IDE Run Arduino demo Check connection on ThingWorx Server   Learn More   We recommend the following resources to continue your learning experience:    Capability Guide Connect Use REST API to Access ThingWorx Build Data Model Introduction   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource Link Community Developer Community Forum Support REST API Help Center
View full tip
Announcements