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

Community Tip - Did you know you can set a signature that will be added to all your posts? Set it here! X

IoT Tips

Sort by:
  Step 4: Add Data   We've added a Waterfall Chart Widget to the Mashup, but we still need to bring in backend data.   Ensure the top-right Data tab is active.   Click the green + button.   In the Entity field, search for and select TPWC_Thing. In the Services field, type getprop. Click the right arrow beside GetProperties. On the right, check Execute on Load.   In the bottom-right of the pop-up, click Done.   Under the Data tab on the right, expand GetProperties.   Drag-and-drop Things_TPWC_Thing > GetProperties > InfoTable_Property onto the Waterfall Chart.   On the Select Binding Target pop-up, click Data.     Widget Properties   With the Waterfall Chart bound to data, we now just need to configure a few of the chart's Properties. With the Waterfall Chart selected in the central Canvas area, ensure the Properties tab is active in the bottom-left.   In the Filter field, type xaxis.   In the XAxisField, search for and select month.   In the Filter field, clear the xaxis search and then start a new filter with usetrend.   Check the UseTrendColors box.   At the top, click Save.     Step 5: View Mashup   Up to this point, we've created a Data Shape to format the columns of an Info Table Property. You then created a Thing, as well as an Info Table Property formatted by the Data Shape. As a test, you added some manually-entered data to the Info Table. After creating a Mashup, you added a Waterfall Chart Widget and tied it to that backend data.   The only thing left to do is to visualize your GUI.    Ensure that you're on the Design tab of the TPWC_Mashup.   At the top, click View Mashup. The end result is a visualization of burn up/down as the project is first defined and then implemented.     Step 6: Next Steps   Congratulations! You've successfully completed the Track Progress with Waterfall Chart guide, and learned how to: Create a Data Shape Create a Thing Create an Info Table Property Populate an Info Table with appropriate data for a Waterfall Chart Create a Mashup Utilize a Waterfall Chart to display project progress  Learn More   We recommend the following resources to continue your learning experience: Capability Guide Manage How to Display Data in Charts Additional Resources   If you have questions, issues, or need additional information, refer to: Resource Link Community Developer Community Forum Support Waterfall Chart Help  
View full tip
    Step 5: Handling and Receiving XML Objects   Working with JSON with JavaScript can be easy and simple. Working with XML while using JavaScript can be more challenging, because XML is so tightly structured. This can affect how you setup code and how you use the Rhino JavaScript engine for your needs.   NOTE: Examples of these services can be found in the ** XMLProcessorThing** entity, which is provided in the download.   Handling XML   XML can be handled using two methods. The first method is converting the XML string to an XML object. The second methos is creating an XML object, then assigning the raw XML to that variable.   The simple XML object is as follows: <note> <to>Janice</to> <from>Billy</from> <heading>Please Remind Me</heading> <body>Take out the trash this weekend!</body> </note> First, create the entity you will use for both methods. In ThingWorx Composer, click the + New at the top of the screen. Select Thing in the dropdown. Name the Thing XMLProcessorThing and click Save. Click the Services tab. Click Save and let’s begin with the first method of handling XML in ThingWorx.   Parsing XML Using Method 1   Now, you will create the service to handle the first method of XML handling. This is a simple method to easily convert XML string and grabbing a field in the XML.   In the Services tab of the XMLProcessorThing Thing, create a new service called ParseXML. The service will have no parameters. Set the Output as String. Add the following JavaScript to help encode the string and return an HTML friendly string. /*jshint multistr: true */ var xml = new XML("<note> \ <to>Janice</to> \ <from>Billy</from> \ <heading>Please Remind Me</heading> \ <body>Take out the trash this weekend!</body> \ </note>"); var result = "Sending note to " + String(xml.*::to);   5. Click Save and you’re all done with this service to parse XML string and grab information from it.   Parsing XML Using Method 2   The second method will show errors and warnings, if you’re using the Lint setting in your service JavaScript code window. This method will be very helpful in handling XML responses from a service call.   In the Services tab of the XMLProcessorThing Thing, create a new service called ParseRawXML. The service will have no parameters. Set the Output as String. Add the following JavaScript to help encode the string and return an HTML friendly string. var xml = new XML(); xml = <note> <to>Janice</to> <from>Billy</from> <heading>Please Remind Me</heading> <body>Take out the trash this weekend!</body> </note> var result = "Sending note to " + String(xml.to);   5. Click Save and you’re all done.     Step 6: Next Steps   Congratulations! You've successfully completed the Sending and Receiving JSON and XML guide, and learned how to use the ThingWorx Platform to handle REST requests and send payload for external SOAP and REST services.   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Design Your Data Model Build Use REST API to Access ThingWorx   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
  Step 5: Format Timed Values   At the top, click the Services section of scts_thing.   In the Ihnerited Services section, you will see the built-in services of the Statistical Calculation Thing Shape. These services can perform a variety of analytical calculations.   Timed Values Service   The Statistical Calculation Thing Shape can only perform analytics operations on time-series datasets. However, accessing a time-series Value Stream can have a performance hit on the system.   Instead, a Property with an Info Table using a timestamp/value Data Shape is used as the universal input to each built-in service of the Statistical Calculation Thing Shape.   For efficiency, we only reference the Value Stream once to create a formatted timedValues that is used as an input to all other service calls.   At the top, click Services.   Click + Add.   In the Name field, enter timed_values_service. In the Javascript field, copy and past the following code: me.timed_values = me.QueryTimedValuesForProperty({ propertyName: "numbers", maxItems: 10, startTime: me.start_time, endTime: me.end_time });   At the bottom, click Save and Execute.   Click Done, and return to Properties and Alerts. On the timed_values property row, click the pencil icon for Set value of property.   In the pop-up, note that there are now seven entries - each with the 1, 5, 9, 5, 9, 1, and 9 values and the timestamps when you entered them.   In the pop-up, click Cancel. If needed, in the top-right, click the icon to close the slide-out.   Step 6: Calculation Services   Now that the numbers, start_time, end_time, and timed_values service inputs have been set, you can use the built-in Services of the Statistical Calculation Thing Shape to perform a variety of analytics calculations.   Mean Service   First, you will utilize the built-in CalculateMeanValue service.   The dataset is the following: 1, 5, 9, 5, 9, 1, 9.   As such, the mean should be (1+5+9+5+9+1+9)/7 = 39/7 = 5.571...   Return to the Services section. At the top, click + Add. In the Name field, enter mean_service. In the Javascript code section, copy and paste the following: me.mean_result = me.CalculateMeanValue({ timedValues: me.timed_values }); At the top, click Save and Continue.   At the bottom, click Execute. Click Done, then return to the Properties and Alerts section. Note that the mean_result property now has the value 5.571....     Median Service   Next, you will utilize the built-in CalculateMedianValue service.   With our dataset having 5 as the middle value, that should be the result.   Return to the Services section. At the top, click + Add. In the Name field, enter median_service. In the Javascript code section, copy and paste the following: me.median_result = me.CalculateMedianValue({ timedValues: me.timed_values }); At the top, click Save and Continue. At the bottom, click Execute. Click Done, and return to the Properties and Alerts section. Note that the median_result Property now has the value 5.     Mode Service   You will now utilize the built-in CalculateModeValue service.   With the dataset having 9 as the most common value, that should be the result.   Return to the Services section. At the top, click + Add. In the Name field, enter mode_service. In the Javascript code section, copy and paste the following: me.mode_result = me.CalculateModeValue({ timedValues: me.timed_values }); At the top, click Save and Continue.   At the bottom, click Execute. Click Done, and return to the Properties and Alerts section. On the mode_result row and under the Value column, click the "pencil" icon for Set value of property.   In the popup, note that the mode_result Property now has the value 9.   Click Cancel to close the popup. If necessary, at the top-right, click the button to close the slide-out.   Standard Deviation Service   Lastly, you will utilize the built-in CalculateStandardDeviationValue service.   There are multiple free Standard Deviation calculators to check the answer.   Accordingly, the Standard Deviation should be 3.59894...   Return to the Service section. At the top, click + Add. In the Name field, enter standarddev_service. In the Javascript code section, copy and paste the following: me.standarddev_result = me.CalculateStandardDeviationValue({ timedValues: me.timed_values }); At the top, click Save and Continue.   At the bottom, click Execute. Click Done, and return to the Properties and Alerts section. Note that the standarddev_result property now has the value 3.59894...       Step 7: Other Options   The Mean, Median, Mode, and Standard Deviation services you have completed are just a sampling of what the Statistical Calculation Thing Shape offers.   Below is a table of additional built-in services:   Calculation Service Name Description Binned Data Distribution for Bin Size CalculateBinnedDataDistributionForBinSize Calculate the binned distribution of data points based on the desired bin size. Binned Data Distribution for Number of Bins CalculateBinnedDataDistributionForNumberOfBins Calculate the binned distribution of data points based on the desired number of bins. Confidence Interval Values CalculateConfidenceIntervalValues Confidence Interval Values Based on a specified confidence interval percentage, calculate the minimum, median, and maximum interval values. Five Number Property Values CalculateFiveNumberPropertyValues Calculate the five number values: minimum, lower quartile, median, upper quartile, and maximum. Fourier Transform CalculateFourierTransform Calculate the results of running the fast Fourier transform on the specified values. Maximum Value CalculateMaximumValue Calculate the maximum property value in the provided infotable. Minimum Value CalculateMinimumValue Calculate the minimum property value in the provided infotable. Sampling Frequency Values CalculateSamplingFrequencyValues Calculate the sampling frequency values: minimum, median, and maximum.     Step 8: Next Steps   Congratulations!   In this guide, you have learned how to:   Create a Value Stream and Data Shape Create a Thing with the Statistical Calculation Thing Shape Modify a property to record values to the Value Stream Utilize various built-in services for analytical calculations   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Build a Predictive Analytics Model Build Operationalize an Analytics Model   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Descriptive Analytics Help Center
View full tip
  Step 5: Add Data   We've added a Pareto Chart Widget to the Mashup, but we still need to bring in backend data.   Ensure the top-right Data tab is active.   Click the green + button.   In the Entity field, search for and select TIPC_Thing. In the Services field, type getprop. Click the right arrow beside GetProperties. On the right, check Execute on Load.   In the bottom-right of the pop-up, click Done.   Under the Data tab on the right, expand GetProperties.   Drag-and-drop Things_TIPC_Thing> GetProperties > InfoTable_Property onto the Pareto Chart.   On the Select Binding Target pop-up, click Data.   With the Pareto Chart selected in the central Canvas area, ensure the Properties tab is active in the bottom-left.   In the Filter field, type xaxis.   In the XAxisField, search for and select month.   At the top, click Save.     Step 6: View Mashup   Up to this point, we've created a Data Shape to format the columns of an Info Table Property. You then created a Thing, as well as an Info Table Property formatted by the Data Shape. As a test, you added some manually-entered data to the Info Table. After creating a Mashup, you added a Pareto Chart Widget and tied it to that backend data.   The only thing left to do is to visualize your GUI.    Ensure that you're on the Design tab of the TIPC_Mashup.   At the top, click View Mashup.   The end result is a visualization of how each of your main issues contribute to your overall downtime.   In particular, this test data shows that excess_temperature is the primary cause of issues, regardless of month.    You could now connect the backend data-storage to live-data from the robotic welding arm to begin an actual determination of your issues.       Step 7: Next Steps   Congratulations! You've successfully completed the Track Issues with Pareto Chart guide, and learned how to:   Create a Data Shape Create a Thing Create an Info Table Property Populate an Info Table with appropriate data for a Pareto Chart Create a Mashup Utilize a Pareto Chart to display issue-aggregation    Learn More   We recommend the following resources to continue your learning experience: Capability  Guide Manage How to Display Data in Charts Additional Resources   If you have questions, issues, or need additional information, refer to: Resource Link Community Developer Community Forum Support Pareto Chart Help  
View full tip
    Step 4: Write Data to External Database You’ve connected to the database, you’re able to query the database. Now let’s handle inserting new data into the database. The update statements and data shown below are based on the table scripts provided in the download. Examples of how the ThingWorx entity should look can be seen in the SQLServerDatabaseController and OracleDatabaseController entities. Running an Insert Follow the steps below to set up a helper service to perform queries for the database. While other services might generate the query to be used, this helper service will be your shared execution service. In the DatabaseController entity, go to the Services tab.   Create a new service of type SQL (Command) called RunDatabaseCommand. Keep the Output as Integer. Add the following parameter:  Name           Base Type       Required command String True 5. Add the following code to your new service: <<command>> 6. Click Save and Continue. Your service signature should look like the below example. You now have a service that can run commands to the database. Run your service with a simple insert. There are two ways to go from here. You can either query the database using services that call this service, or you can create more SQL Command services that query the database directly. Let’s go over each method next, starting with a service to call the helper. In the Services tab of the DatabaseController entity, create a new service of type JavaScript. Name the service JavaScriptInsert_PersonsTable. Set the Output as InfoTable, but do not set the DataShape for the InfoTable. Add the following code to your new service: try { var command = "INSERT INTO Persons (person_key, person_name_first, person_name_last, person_email, person_company_name, " + "person_company_position, person_addr1_line1, person_addr1_line2, person_addr1_line3, person_addr1_city, person_addr1_state, " + "person_addr1_postal_code, person_addr1_country_code, person_addr1_phone_number, person_addr1_fax_number, person_created_by, " + "person_updated_by, person_created_date, person_updated_date) VALUES ('" + key + "', '" + name_first + "', '" + name_last + "', '" + email + "', '" + company_name + "', '" + company_position + "', '" + addr1_line1 + "', '" + addr1_line2 + "', '" + addr1_line3 + "', '" + addr1_city + "', '" + addr1_state + "', '" + addr1_postal_code + "', '" + addr1_country_code + "', '" + addr1_phone_number + "', '" + addr1_fax_number + "', '" + created_by + "', '" + updated_by + "', '" + created_date + "', '" + updated_date + "')"; logger.debug("DatabaseController.JavaScriptInsert_PersonsTable(): Query - " + command); var result = me.RunDatabaseCommand({command: command}); } catch(error) { logger.error("DatabaseController.JavaScriptInsert_PersonsTable(): Error - " + error.message); } 5. Add the following parameter:  Name                                   Base Type           Required key String True name_first String True name_last String True company_name String True company_position String True addr1_line1 String True addr1_line2 String True addr1_line3 String True addr1_city String True addr1_state String True addr1_postal_code String True addr1_country_code String True addr1_phone_number String True addr1_fax_number String True created_by String True updated_by String True created_date String True updated_date String True 6. Click Save and Continue. Any parameter, especially those that were entered by users, that is being passed into a SQL Statement using the Database Connectors should be fully validated and sanitized before executing the statement! Failure to do so could result in the service becoming an SQL Injection vector. Now, let’s utilize a second method to create a query directly to the database. You can use open and close brackets for parameters for the insert. You can also use <> as a method to mark a value that will need to be replaced. As you build your insert statement, use [[Parameter Name]] for parameters/variables substitution and <<string replacement >> for string substitution. In the Services tab of the DatabaseController entity, create a new service of type SQL (Command).   Name the service SQLInsert_PersonsTable. Add the following code to your new service: INSERT INTO Persons (person_key ,person_name_first ,person_name_last ,person_email ,person_company_name ,person_company_position ,person_addr1_line1 ,person_addr1_line2 ,person_addr1_line3 ,person_addr1_city ,person_addr1_state ,person_addr1_postal_code ,person_addr1_country_code ,person_addr1_phone_number ,person_addr1_fax_number ,person_created_by ,person_updated_by ,person_created_date ,person_updated_date) VALUES ([[key]] ,[[name_first]] ,[[name_last]] ,[[email]] ,[[company_name]] ,[[company_position]] ,[[addr1_line1]] ,[[addr1_line2]] ,[[addr1_line3]] ,[[addr1_city]]]] ,[[addr1_state]] ,[[addr1_postal_code]] ,[[addr1_country_code]] ,[[addr1_phone_number]] ,[[addr1_fax_number]] ,[[created_by]] ,[[updated_by]] ,[[created_date]] ,[[updated_date]]); 4. Add the following parameter:  Name                                  Base Type       Required key String True name_first String True name_last String True company_name String True company_position String True addr1_line1 String True addr1_line2 String True addr1_line3 String True addr1_city String True addr1_state String True addr1_postal_code String True addr1_country_code String True addr1_phone_number String True addr1_fax_number String True created_by String True updated_by String True created_date String True updated_date String True 5. Click Save and Continue. Examples of insert services can be seen in the provided downloads.   Step 5: Executing Stored Procedures There will be times when a singular query will not be enough to get the job done. This is when you'll need to incorporate stored procedures into your database design. ThingWorx is able to use the same SQL Command when executing a stored procedure with no data return and a SQL query when executing a stored procedure with an expected result set. Before executing these services or stored procedures, ensure they exist in your database. They can be found in the example file provided. Execute Stored Procedure Now, let's create the service to handle calling/executing a stored procedure. If you are expecting data from this stored procedure, use EXEC to execute the stored procedure. If you only need to execute the stored procedure and do not expect a result set, then using the EXECUTE statement is good enough. You're also able to use the string substitution similar to what we've shown you in the earlier steps. In the DatabaseController entity, go to the Services tab. Create a new service of type SQL (Command) called RunAssignStudentStoredProcedure. Add the following parameter:  Name                      Base Type        Required student_key String True course_key String True 4. Add the following code to your new service: EXECUTE AddStudentsToCourse @person_key = N'<<person_key>>', @course_key = N'<<course_key>>';   You can also perform this execute in a service based on JavaScript using the following code: try { var command = "EXECUTE AddStudentsToCourse " + " @student_key = N'" + student_key + "', " + " @course_key = N'" + course_key + "'"; logger.debug("DatabaseController.RunAssignStudentStoredProcedure(): Command - " + command); var result = me.RunDatabaseCommand({command:command}); } catch(error) { logger.error("DatabaseController.RunAssignStudentStoredProcedure(): Error - " + error.message); } 5. Click Save and Continue. Execute Stored Procedure for Data Let's create the entity you will use for both methods. This can be seen in the example below:   In the DatabaseController entity, go to the Services tab. Create a new service of type SQL (Query) called GetStudentCoursesStoredProcedure. Set the Output as InfoTable, but do not set the DataShape for the InfoTable. Add the following parameter:  Name                    Base Type        Required course_key String True 5. Add the following code to your new service: EXEC GetStudentsInCourse @course_key = N'<<course_key>>'   You can also perform this execute in a service based on JavaScript using the following code: try { var query = "EXEC GetStudentsInCourse " + " @course_key = N'" + course_key + "'"; logger.debug("DatabaseController.GetStudentCoursesStoredProcedure(): Query - " + query); var result = me.RunDatabaseQuery({query:query}); } catch(error) { logger.error("DatabaseController.GetStudentCoursesStoredProcedure(): Error - " + error.message); } 6. Click Save and Continue. You've now created your first set of services used to call stored procedures for data. Of course, these stored procedures will need to be in the database before they can successfully run. Step 6: Next Steps Congratulations! You've successfully completed the guide for External Database, and learned how to use the ThingWorx Platform to connect to database, query for data, and write new data. Learn More We recommend the following resources to continue your learning experience:  Capability       Guide Build Design Your Data Model Build Configure Permissions Additional Resources If you have questions, issues, or need additional information, refer to:  Resource           Link Community Developer Community Forum
View full tip
  Step 5: Add Data   Now that our Mashup's Layout and Widgets have been set, we need to bring in backend data and tie it to those Widgets for display.    We'll make use of Mashup Data Services for this. The first one we'll add will be UserManagementSubsystem > GetUserCount.   Ensure that the Data tab in the top-right is active.   Click the + icon.   In the Entity field, search for and select UserManagementSubsystem.   In the Services field, type GetUserCount.   Beside the GetUserCount Service, click the right arrow. Under Selected Services, check the box for Execute on Load.     Add LicensingSubsystem > GetCurrentLicenseInfo   You're not limited to only pulling information from one Mashup Data Service.   We already have User Management's GetUserCount. We'll now also bring in information from the Licensing Subsystem.   On the same Add Data pop-up, click the X beside UserManagementSubsystem to clear it.   In the Entity field, search for and select LicensingSubsystem.   In the Services field, type GetCurrentLicenseInfo.   Beside GetCurrentLicenseInfo, click the right arrow. Under Selected Services on the GetCurrentLicenseInfo line, check the box for Execute on Load.   On the bottom-right of the pop-up, click Done.   At the top, click Save.   Bind Data   With our backend data now accessible, let's bind it to our Widgets for display.   On the Data tab, expand Subsystems_LicensingSubsystem > GetCurrentLicenseInfo > Returned Data.   Drag-and-drop Licensing's All Data onto the Grid Advanced Widget in the bottom section.   On the Select Binding Target pop-up, click Data.   Expand Subsystems_UserManagementSubsystem > GetUserCount > Returned Data > All Data.   Drag-and-drop User Management's result onto the Text Field Widget in the top section.   On the Select Binding Target pop-up, click Text.   At the top, click Save.   Automatically Refresh   If we were to click View Mashup now, we would see the User Count and Licensing info displayed in the Mashup's Widgets. However, it would never update unless we manually refreshed the page.   To automate that process, we'll use the Auto Refresh Widget.   In the top section of the Mashup, click the Auto Refresh Widget to select it.   On the top-left of the Auto Refresh Widget, click the drop-down icon to reveal additional options.   Drag-and-drop the Refresh Event onto GetCurrentLicenseInfo.   Repeat steps 1-3 to drag-and-drop the Refresh Event onto GetUserCount also.   With the Auto Refresh Widget still selected, browse the Properties section in the bottom-left.   Change RefreshInterval to 5, and hit your keyboard's Tab key to lock in the change. This will cause the Refresh Event to fire every 5 seconds.   Click Save. Click View Mashup.     Step 6: Replace License   We have now created a Minimum Viable Product (MVP) of a "licensing dashboard" to ease our administration work.   This dashboard could still be improved. For instance, a Mashup Function could be created which automatically recalculates the value from GetUserCount to more accurately match GetCurrentLicenseInfo. This can be accomplished via the Mashup Builder's bottom-right Functions tab. Or, you could even add a separate Text Field Widget to to the top section and directly access the remaining license time via the LicensingSubsystem > GetDaysRemainingInLicense Service.    Whatever you choose to do to improve the Mashup is up to you.   However, what should be done when a license is nearing its expiration? To resolve this issue, we need to replace the existing license via the AcquireLicense Service.   Within the OS of the Foundation server, navigate to the file-system folder where the current license_capability_response.bin is located. This is typically the ThingworxPlatform folder.   Move the existing license_capability_response.bin and any other existing *.bin files to another location for backup. Note that this is EXTREMELY important, as if anything goes wrong, you want to be able to restore the original license. It is very important to ensure that only one *.bin file exists in the appropriate folder Place the new .bin file into the appropriate folder and rename it to license_capability_response.bin. In Foundation, navigate to the LicensingSubsystem > Services page.   On the AcquireLicense row, click the "play" icon for Execute Service.   On the bottom-right of the pop-up, click Execute. Note that if you receive an error, it will be necessary to restart the ThingWorx Tomcat service.  The act of restarting the service will automatically load the new license.   To close the pop-up, click Done.   After acquiring your new license, you should immediately return to the LicensingSubsystem and consult the GetCurrentLicenseInfo Service to confirm that Thing, User, expiration-date, and other issues are accurate.   If anything goes wrong with the new license transfer, you can simply replace the original license_capability_response.bin file and re-run AcquireLicense to return to your old one. Once again, it is import to perform these steps well before your expiration occurs.    Foundation checks for a valid license periodically. If this happens while you have an invalid license_capability_response.bin file in-place, you will no longer be able to access the Foundation GUI.    Fortunately, these issues are self-correcting if a valid license_capability_response.bin is placed in the correct location, as these periodic checks will also pick up a valid license_capability_response.bin file automatically, even after the system has locked you out.    You should also be able to trigger an AcquireLicense action via a REST call even if the GUI is unavailable.      Step 7: Next Steps   Congratulations! You've successfully completed the Manage Licensing with Foundation Subsystems guide.   In this guide, you learned how to:   Access the Foundation Subsystems Execute built-in Services to retrieve: User counts Thing counts License expiration count Create a "License Dashboard" Mashup Update to a new License    Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support Foundation Help Center  
View full tip
  Step 6: Create OPC UA Tag in ThingWorx   We will now create a Device in Kepware with a Tag whose value will be shown in ThingWorx.   Right-click on Channel1 that was just created, then click Next to accept the default name Device1       Click Next six times to accept the default settings, Then click the Select import items button.     Expand the remote OPC UA server URL, then expand OpcPlc and Telemetry.     Click SlowUint1 to select it, then click Add items >>. Click OK, Next, Finish. Return to ThingWorx Composer. Under Browse > Modeling > Industrial Connections, open IndConn_Server. Expand Channel1 > Device1 > OpcPlc, then click Telemetry.     Click the check-box next to SlowUint1. Click Bind to New Entity.     Select RemoteThing, then click OK. Enter azure-opcua-plc in the Name field, then click Save.     Click Properties and Alerts, then Click Refresh to see the property value changing every 10 seconds.     Step 7: Next Steps   Congratulations! You've successfully completed the Connect to an Azure OPC UA Server guide, and learned how to:   Create an OPC UA Server in Azure Configure Kepware as on OPC UA Client Connect Kepware to ThingWorx Foundation Monitor OPC UA data in ThingWorx Composer   Learn More   We recommend the following resources to continue your learning experience: Capability Guide Experience Create Your Application UI   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Getting Started with ThingWorx Documentation Kepware documentation Support Kepware Support site
View full tip
  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 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
  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 5: Log to Value Stream   Now that you have explored the Properties of IndConn_Tag1, you’ve seen how ThingWorx Kepware Server feeds information to ThingWorx Foundation. To get an even better indication of changes and confirm continued connectivity, we will log the changes to a Value Stream in order to record the values with a TimeStamp.   Create Value Stream   Return to the ThingWorx Foundation New Composer browser. Click Browse. Click Data Storage -> Value Streams. Click + New. In the Choose Template pop-up, select ValueStream. Click OK. Type IndConn_ValueStream in the Name field. If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. In the Description field, enter an appropriate description, such as Value Stream to record changes from ThingWorx Kepware Server. Click Save.   Bind Value Stream   Open the IndConn_Tag1 either by clicking on the tab at the top, or by clicking on PTCDefaultProject on the left At the top, select General Information. In the Value Stream field, enter indconn. Select IndConn_ValueStream from the sorted list. At the top, select Properties and Alerts. Click Simulation_Examples_Functions_Random3. A new set of options will expand from the right. Check the box for Persistent. Check the box for Logged. Click the Check button to close the expanded options. Click Save. All changes to the Random3 Tag, fed from ThingWorx Kepware Server, are now stored and TimeStamped in the Simulation_Examples_Functions_Random3 Property.   Step 6: Visualize the Data   We'll now create a Mashup to visualize the record of information from ThingWorx Kepware Server. In ThingWorx Foundation's Browse, click Visualization -> Mashups. Click +New. In the New Mashup pop-up, leave the default selections. Click OK. In the Name field, enter IndConn_Mashup. If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. At the top, click Save. At the top, click Design. In the Filter Widgets field at the top-left, enter chart. Drag-and-drop a Line Chart onto the central canvas area. Add Data   On the right-side of the Mashup Builder, click the Data tab. Click the + button on the Data tab.        3. In the Add Data pop-up, enter indconn in the Entity field, overwriting Filter. 4. Select IndConn_Tag1 from the sorted list. 5. In the Filter field below Services, enter queryprop. 6. Click the right arrow button beside QueryPropertyHistory. The QueryPropertyHistory Service of the IndConn_Tag1 Thing will appear on the right in the Selected Services field. 7. Check the box under Execute on Load in the Selected Services field.' 8. Click Done. Note that the QueryPropertyHistory Service now appears on the right side Data tab. 9. Click the arrow to expand QueryPropertyHistory, then click to expand Returned Data. 10. Drag-and-drop All Data from the QueryPropertyHistory Service from the right onto the Time Series Chart in the center. 11. In the Select Binding Target pop-up, select Data.        Configure Chart Properties   In the bottom-left Properties of timeserieschart-1, enter xaxisfield in the Filter Properties field. Expand the drop-down for XAxisField. Select timestamp. Click Save. Click View Mashup. (You may have to enable pop-ups to view the mashup.) The IndConn_Mashup will show you the recorded history of property changes that came from ThingWorx Kepware Server. NOTE: If the Mashup visualization is blank, confirm your connection to IndConn. Return to the Test Connection section of the Bind Industrial Tag step.   Step 7: Next Steps   Congratulations! You've successfully completed the Connect Kepware Server to ThingWorx Foundation guide. You've learned how to: Connect ThingWorx Foundation to ThingWorx Kepware Server Map Tags to Properties     The next guide in the Connect and Monitor Industrial Plant Equipment learning path is Create Industrial Equipment Model. 
View full tip
Connect Kepware Server to ThingWorx Foundation Guide Part 1   Overview   This guide has step-by-step instructions for connecting ThingWorx Kepware Server to ThingWorx Foundation. This guide will demonstrate how easily industrial equipment can be connected to ThingWorx Foundation without installing any software on production equipment. NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL 2 parts of this guide is 30 minutes.    Step 1: Learning Path Overview     This guide explains the steps to connect ThingWorx Kepware Server with ThingWorx Foundation and is part of the Connect and Monitor Industrial Plant Equipment Learning Path. You can use this guide independently from the full Learning Path. If you want to learn to connect ThingWorx Kepware Server to ThingWorx Foundation, this guide will be useful to you. When used as part of the Industrial Plant Learning Path, you should have already installed ThingWorx Kepware Server and created an Application Key. In this guide, we will send information from ThingWorx Kepware Server into ThingWorx Foundation. Other guides in this learning path will use Foundation's Mashup Builder to construct a website dashboard that displays information and from ThingWorx Kepware Server. We hope you enjoy this Learning Path.   Step 2: Create Gateway   To make a connection between ThingWorx Kepware Server and Foundation Server, you must first create a Thing. WARNING: To avoid a timeout error, create a Thing in ThingWorx Foundation BEFORE attempting to make the connection in ThingWorx Kepware Server. In ThingWorx Foundation 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 Description field, enter an appropriate description, such as Industrial Gateway Thing to connect to ThingWorx Kepware Server.   In the Base Thing Template field, enter indus, then select the IndustrialGateway Thing template from the sorted list. Click Save.   Step 3: Connect to Foundation   Now that you’ve created an IndustrialGateway Thing and an Application Key, you can configure ThingWorx Kepware Server to connect to ThingWorx Foundation. Return to the ThingWorx Kepware Server Windows application. Right-click Project. Select Properties….       4. In the Property Editor pop-up, click ThingWorx.       5. In the Enable field, select Yes from the drop-down.       6. In the Host field, enter the URL or IP address of your ThingWorx Foundation server, Do not enter http://       7. Enter the Port number. If you are using the "hosted" Developer Portal trial, enter 443. 8. In the Application Key field, copy and paste the Application Key you just created. 9. In the Trust self-signed certificates field, select Yes from the drop-down. 10. In the Trust all certificates field, select Yes from the drop-down. 11. In the Disable encryption field, select No from the drop-down if you are using a secure port. Select Yes if you are using an http port. 12. Type IndConn_Server in the Thing name field, including matching capitalization. 13. 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. 14. Click Apply in the pop-up. 15. Click Ok. In the ThingWorx Kepware Server Event window at the bottom, you should see a message indicating Connected to ThingWorx.   NOTE: If you do not see the "Connected" message, repeat the steps above, ensuring that all information is correct. In particular, check the Host, Port, and Thing name fields for errors.   Step 4: Bind Industrial Tag   Now that you've established a connection, you can use ThingWorx Foundation to inspect all available information on ThingWorx Kepware Server. ThingWorx Kepware Server includes some information by default to assist you with verifying a valid connection with ThingWorx Foundation. Create New Thing Return to ThingWorx Foundation. Click Browse. Click Modeling -> Industrial Connections.   Click IndConn_Server. At the top, click Discover.   The Discover option is exclusive to Things inheriting the IndustrialGateway Thing Template and displays information coming from ThingWorx Kepware Server. Expand Simulation Examples. Click Functions.   On the right, you’ll see several pre-defined Tags to assist with connectivity testing. Click the checkbox next to Random3. Click Bind to New Entity.   In the Choose Template pop-up, select RemoteThing and click OK.   Finalize New RemoteThing   You’ll now be in an interface to create a new Thing with a predefined Property based on ThingWorx Kepware Server Tag1. Type IndConn_Tag1 in the Name field. If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. In the Description field, enter an appropriate description, such as Thing with a property fed from an Kepware Server Tag. The Base Thing Template has been automatically set to RemoteThing. The Implemented Shapes has been automatically set to IndustrialThingShape. 4. Click Save.   Test Connection   The IndConn_Tag1 Thing you created now has a Property with a value that will change with each update from ThingWorx Kepware Server. The Tag1 we utilized is a 'ramp' and therefore, the value will increase at regular intervals. At the top, click Properties and Alerts. Under Inherited Properties, you will see entries for both RemoteThing and IndustrialThingShape. The Property isConnected is checked, indicating a connection from Foundation to ThingWorx Kepware Server. The Property IndustrialThing has been automatically set to IndConn_Server. Notice the predefined Property named Simulation_Examples_Functions_Random3.   Click Refresh repeatedly. You’ll see the value increase with each Refresh. This represents data being simulated in ThingWorx Kepware Server. Click  here to view Part 2 of this guide.  
View full tip
  Step 7: Delivery Truck Model    In the Delivery Truck application, there are three Delivery Truck Things. Each Thing has a number of Properties based on its location, speed, and its deliveries carried out. In this design, when a delivery is made or the truck is no longer moving, the property values are updated. The DeliveryTruckThing class extends the VirtualThing class and based on the DeliveryTruck Entities in the Composer. After extending VirtualThing, there are a number of steps necessary to get going. For the DeliveryTruckThing and SimpleThing classes, there are a number of methods for creating Properties, Events, Services, and Data Shapes for ease of use.   The constructor for the DeliveryTruckThing takes in the name of the Thing, the description of the Thing, and the ConnectedThingClient instance used to make the connection. It then sends these values to the VirtualThing constructor as shown below.   public DeliveryTruckThing(String name, String description, ConnectedThingClient client) { super(name, description, client); ...   We use the initializeFromAnnotations method to initialize all of the annotations that we will create in this class. This is done as follows and a necessary call for VirtualThings in the constructor:   initializeFromAnnotations();   Create Properties   You can create Properties in two ways. Using annotations is the recommended method, but there are times in which programmatically creating Properties is the best option. For example, constructing dynamic features or allowing inline functionality would call for the coding style of Property creation. The following shows the Properties that correlate to those in the DeliveryTruck Entities in the Composer. To do this within the code, you would use a PropertyDefinition instance as shown in the SimpleThing.java property1 creation.   With Annotation @SuppressWarnings("serial") @ThingworxPropertyDefinitions(properties = { @ThingworxPropertyDefinition(name="Driver", description="The name of the driver", baseType="STRING", aspects={"isReadOnly:false"}), @ThingworxPropertyDefinition(name="DeliveriesLeft", description="The number of deliveries left", baseType="NUMBER", aspects={"isReadOnly:false"}), @ThingworxPropertyDefinition(name="Speed", description="The speed of the truck", baseType="NUMBER", aspects={"isReadOnly:false"}), @ThingworxPropertyDefinition(name="Location", description="The location of the truck", baseType="LOCATION", aspects={"isReadOnly:false"}), @ThingworxPropertyDefinition(name="TotalDeliveries", description="The number of deliveries", baseType="NUMBER", aspects={"isReadOnly:false"}), @ThingworxPropertyDefinition(name="DeliveriesMade", description="The number of deliveries made", baseType="NUMBER", aspects={"isReadOnly:false"}), })   Without Annotation //Create the property definition with name, description, and baseType PropertyDefinition property1 = new PropertyDefinition(property, "Description for Property1", BaseTypes.BOOLEAN); //Create an aspect collection to hold all of the different aspects AspectCollection aspects = new AspectCollection(); //Add the dataChangeType aspect aspects.put(Aspects.ASPECT_DATACHANGETYPE, new StringPrimitive(DataChangeType.NEVER.name())); //Add the dataChangeThreshold aspect aspects.put(Aspects.ASPECT_DATACHANGETHRESHOLD, new NumberPrimitive(0.0)); //Add the cacheTime aspect aspects.put(Aspects.ASPECT_CACHETIME, new IntegerPrimitive(0)); //Add the isPersistent aspect aspects.put(Aspects.ASPECT_ISPERSISTENT, new BooleanPrimitive(false)); //Add the isReadOnly aspect aspects.put(Aspects.ASPECT_ISREADONLY, new BooleanPrimitive(false)); //Add the pushType aspect aspects.put("pushType", new StringPrimitive(DataChangeType.NEVER.name())); //Add the defaultValue aspect aspects.put(Aspects.ASPECT_DEFAULTVALUE, new BooleanPrimitive(true)); //Set the aspects of the property definition property1.setAspects(aspects); //Add the property definition to the Virtual Thing this.defineProperty(property1);   Property values can either be set with defaults using the aspects setting. Nevertheless, setting a default value will affect the Property in the ThingWorx platform after binding. It will not set a local value in the client application. In this example, we make a request to the ThingWorx Composer for the current values of the delivery truck properties using our getter methods:   //Get the current values from the ThingWorx Composer deliveriesMade = getDeliveriesMade(); deliveriesLeft = getDeliveriesLeft(); totalDeliveries = getTotalDeliveries(); driver = getDriver(); speed = getSpeed(); location = getLocation();   Create Event Definitions   As with Properties, Events can be created using annotations or code as shown in SimpleThing.java. Here we create the DeliveryStop event that is in the DeliveryTruck instances.   With Annotation @ThingworxEventDefinitions(events = { @ThingworxEventDefinition(name="DeliveryStop", description="The event of a delivery truck stopping to deliver a package.", dataShape="DeliveryTruckShape", isInvocable=true, isPropertyEvent=false) })   Without Annotation //Create the event definition with name and description EventDefinition event1 = new EventDefinition(event, "Description for Event1"); //Set the event data shape event1.setDataShapeName("SimpleDataShape"); //Set remote access event1.setLocalOnly(false); //Add the event definition to the Virtual Thing this.defineEvent(event1);   Create Remote Services   With remote Services, the implementation is handled by the Java application and can be called either within the application or remotely, by the Composer while a connection is established. The GetTruckReadings Service, a dummy Service used as an example of how to create a remote Service, populates an Info Table and returns that Info Table for whoever would like to use it. You can see how it is possible to define remote Services that can later be bound to Things in the Composer. A Service is defined using @ThingworxServiceDefinition annotation and its result is defined using @ThingworxServiceResult. These annotations take various parameters among including:   Name Description baseType Aspects In the second line, you can see the name of the result being set by the CommonPropertyNames field to keep development consistent with creating Things in the Composer.   With Annotation @ThingworxServiceDefinition(name="GetTruckReadings", description="Get Truck Readings") @ThingworxServiceResult(name=CommonPropertyNames.PROP_RESULT, description="Result", baseType="INFOTABLE", aspects={"dataShape:DeliveryTruckShape"})   Without Annotation //Create the service definition with name and description ServiceDefinition service1 = new ServiceDefinition(service, "Description for Service1"); //Create the input parameter to string parameter 'name' FieldDefinitionCollection fields = new FieldDefinitionCollection(); fields.addFieldDefinition(new FieldDefinition("name", BaseTypes.STRING)); service1.setParameters(fields); //Set remote access service1.setLocalOnly(false); //Set return type service1.setResultType(new FieldDefinition(CommonPropertyNames.PROP_RESULT, BaseTypes.STRING)); //Add the service definition to the Virtual Thing this.defineService(service1); //Service1 Definition public String Service1(String name) throws Exception { String result = "Hello " + name; return result; }     Create Data Shapes   Data Shapes must be created using code as seen in DeliveryTruckThing.java as shown below:   // Data Shape definition that is used by the delivery stop event // The event only has one field, the message FieldDefinitionCollection fields = new FieldDefinitionCollection(); fields.addFieldDefinition(new FieldDefinition(ACTIV_TIME_FIELD, BaseTypes.DATETIME)); fields.addFieldDefinition(new FieldDefinition(DRIVER_NAME_FIELD, BaseTypes.STRING)); fields.addFieldDefinition(new FieldDefinition(TRUCK_NAME_FIELD, BaseTypes.BOOLEAN)); fields.addFieldDefinition(new FieldDefinition(TOTAL_DELIVERIES_FIELD, BaseTypes.NUMBER)); fields.addFieldDefinition(new FieldDefinition(REMAIN_DELIVERIES_FIELD, BaseTypes.NUMBER)); fields.addFieldDefinition(new FieldDefinition(LOCATION_FIELD, BaseTypes.LOCATION)); defineDataShapeDefinition("DeliveryTruckShape", fields);   NOTE: It is possible to create a Data Shape, and then use it in a Service definition within your code as StringIndex property, StringMap Data Shape, and StringMapService Service in SimpleThing.java.     Scan Cycles   To complete the implementation of the VirtualThing class, we recommend you provide an override and implementation to the processScanRequest method. This method provides a universal method for all VirtualThing implementations. This method could be used or a new method could be created for this purpose. The processScanRequest method in VirtualThing.java does not have an implementation of its own. An implementation from DeliveryTruckThing.java can be seen below:   // The processScanRequest is called by the DeliveryTruckClient every scan cycle @Override public void processScanRequest() throws Exception { // Execute the code for this simulation every scan this.scanDevice(); this.updateSubscribedProperties(1000); this.updateSubscribedEvents(1000); }   Bound Properties in Cycle   The scanDevice method in DeliveryTruckThing.java performs a number of tasks from retrieving property values to firing events. To retrieve a property using binding, a request is made to the client using the name of the property. A good programming practice is to handle how these properties are accessed and set. Note that the update method for properties and events must be used after queueing an event or setting a Property value. In the example below, getter and setter methods are used for added control. The getProperty() call is used on the VirtualThing:   public Double getSpeed() { return (Double) getProperty("Speed").getValue().getValue(); } public void setSpeed() throws Exception { setProperty("Speed", this.speed); } public Location getLocation() { return (Location) getProperty("Location").getValue().getValue(); } public void setLocation() throws Exception { setProperty("Location", this.location); }     Step 8: Services and Events   Events and Services can be very useful. Events are a good way to make a Service be asynchronous. You’re able to call a Service, let it return and then your Entity can subscribe to your Event and not keep the original Service function waiting. Events are also a good way to allow the platform to respond to data when it arrives on the edge device without it having to poll the edge device for updates. The DeliveryTruck Entities in the Composer contains a remote Event. You can find a remote Service within the SimpleThing_1 entity.   Fire Event To fire an Event, create a ValueCollection instance, and load it with the necessary fields for the Data Shape of that Event. Then, send the client the request to fire the Event with the collected values, the Event, and information to find the Entity the Event belongs to as shown below in DeliveryTruckThing.java:   // Set the event information of the defined data shape for a truck stop event ValueCollection payload = new ValueCollection(); // Set values to the fields payload.put(LOCATION_FIELD, new LocationPrimitive(location)); payload.put(REMAIN_DELIVERIES_FIELD, new NumberPrimitive(deliveriesLeft)); payload.put(ACTIV_TIME_FIELD, new DatetimePrimitive(DateTime.now())); payload.put(TOTAL_DELIVERIES_FIELD, new NumberPrimitive(totalDeliveries)); payload.put(DRIVER_NAME_FIELD, new StringPrimitive(driver)); payload.put(TRUCK_NAME_FIELD, new StringPrimitive(super.getBindingName())); // This will trigger the 'DeliveryStop' of a remote thing // on the platform. super.queueEvent("DeliveryStop", new DateTime(), payload);   Execute Service   To execute a Service, you must create a ValueCollection instance, and load it with the necessary parameters of the Service. The ValueCollection is created only when Services and Events are not defined by annotations. Afterwards, you would send the client the request to execute the Service with the parameter values, the Service name, the timeout setting in milliseconds for the Service to finish executing, and information to find the Entity the Service belongs to as shown below in SimpleThingClient.java:   public String callService(String name) throws Exception{ ValueCollection payload = new ValueCollection(); payload.put("name", new StringPrimitive("Timothy")); InfoTable table = handleServiceRequest(service, payload); return table.getFirstRow().getStringValue("name"); }   TIP: The code for creating the Service and Event should be in the constructor of the extended VirtualThing (or a method called from the constructor). Also, the Service code examples will work as long as the actual Service is defined. You can see from the examples that the annotation method is much cleaner.     Click here view Part 5 of this guide.
View full tip
    Step 6: Power Grid Example   In the Power Grid application, there are three Generator Things and three Consumers. Each Thing has a number of Properties based on its location, wattage, and its power lines provided with power. In this design, when a generator goes offline, comes back online, or one of the other power grid aspects are updated/created/deleted, the Property values are updated. The GeneratorThing class extends the VirtualThing class and based on the Generator entities in the Composer. After extending VirtualThing, there are a number of steps necessary to get going. For the GeneratorThing and SimpleThing classes, there are a number of methods for creating Properties, Events, Services, and Data Shapes for ease of use.   The constructor for the GeneratorThing takes in the type of electricity generator, name of the Thing, the description of the Thing, and the ConnectedThingClient instance used to make the connection. It then sends these values to the VirtualThing constructor as shown below. public GeneratorThing(String type, String name, String description, ConnectedThingClient client) { super(name, description, client); ...   We use the initializeFromAnnotations method to initialize all of the annotations that we will create in this class. This is done as follows and a necessary call for VirtualThings in the constructor:   initializeFromAnnotations();   Create Properties   You can create Properties in two ways. Using annotations is the recommended method, but there are times in which programmatically creating properties is the best option. For example, constructing dynamic features or allowing inline functionality would call for the coding style of Property creation. The following shows the Properties that correlate to those in the DeliveryTruck Entities in the Composer. To do this within the code, you would use a PropertyDefinition instance as shown in the SimpleThing.java property1 creation.   With Annotation @ThingworxPropertyDefinition(name="GeneratorType", description="Type of generator", baseType="STRING", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Wattage", description="Wattage produced", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Amps", description="Amps", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Voltage", description="Voltage", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="UpTime", description="Number of minutes since the generator connected online", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Status", description="Status of the generator", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Location", description="Location of the generator", baseType="LOCATION", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="LastSync", description="The last time we performed a sync", baseType="DATETIME", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="ConnectedSince", description="Time where we last performed a successful connection", baseType="DATETIME", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="TransmissionLines", description="An infotable of power lines", baseType="INFOTABLE", aspects={"isReadOnly:false"}) Without Annotation //Create the property definition with name, description, and baseType PropertyDefinition property1 = new PropertyDefinition(property, "Description for Property1", BaseTypes.BOOLEAN); //Create an aspect collection to hold all of the different aspects AspectCollection aspects = new AspectCollection(); //Add the dataChangeType aspect aspects.put(Aspects.ASPECT_DATACHANGETYPE, new StringPrimitive(DataChangeType.NEVER.name())); //Add the dataChangeThreshold aspect aspects.put(Aspects.ASPECT_DATACHANGETHRESHOLD, new NumberPrimitive(0.0)); //Add the cacheTime aspect aspects.put(Aspects.ASPECT_CACHETIME, new IntegerPrimitive(0)); //Add the isPersistent aspect aspects.put(Aspects.ASPECT_ISPERSISTENT, new BooleanPrimitive(false)); //Add the isReadOnly aspect aspects.put(Aspects.ASPECT_ISREADONLY, new BooleanPrimitive(false)); //Add the pushType aspect aspects.put("pushType", new StringPrimitive(DataChangeType.NEVER.name())); //Add the defaultValue aspect aspects.put(Aspects.ASPECT_DEFAULTVALUE, new BooleanPrimitive(true)); //Set the aspects of the property definition property1.setAspects(aspects); //Add the property definition to the Virtual Thing this.defineProperty(property1); Property values can either be set with defaults using the aspects setting. Nevertheless, setting a default value will affect the Property in the ThingWorx platform after binding. It will not set a local value in the client application. In this example, we make a request to the ThingWorx Composer for the current values of the generator properties using our getter methods: //Get the current values from the ThingWorx Composer wattage = getGeneratorWattage(); voltage = getGeneratorVoltage(); location = getLocation();   Create Event Definitions   As with Properties, Events can be created using annotations or code as shown in SimpleThing.java. Here we create the GeneratorOffline event that is in the Generator instances.   With Annotation   @ThingworxEventDefinitions(events = { @ThingworxEventDefinition(name="GeneratorOffline", description="The event of a generator going offline", dataShape="GeneratorShape", isInvocable=true, isPropertyEvent=false) })   Without Annotation   //Create the event definition with name and description EventDefinition event1 = new EventDefinition(event, "Description for Event1"); //Set the event data shape event1.setDataShapeName("SimpleDataShape"); //Set remote access event1.setLocalOnly(false); //Add the event definition to the Virtual Thing this.defineEvent(event1);   Create Remote Services   With remote Services, the implementation is handled by the Java application and can be called either within the application or remotely, by the Composer while a connection is established. The GetTruckReadings Service, a dummy Service used as an example of how to create a remote Service, populates an Info Table and returns that Info Table for whoever would like to use it. You can see how it is possible to define remote Services that can later be bound to Things in the Composer. A Service is defined using @ThingworxServiceDefinition annotation and its result is defined using @ThingworxServiceResult. These annotations take various parameters among including:   Name Description baseType Aspects In the second line, you can see the name of the result being set by the CommonPropertyNames field to keep development consistent with creating Things in the Composer. With Annotation @ThingworxServiceDefinition(name="OhmsLawCalculator", description="Get the watts/power (W) based on input voltage (V) and current (I)") @ThingworxServiceResult(name=CommonPropertyNames.PROP_RESULT, description="Result", baseType="NUMBER")   Without Annotation //Create the service definition with name and description ServiceDefinition service1 = new ServiceDefinition(service, "Description for Service1"); //Create the input parameter to string parameter 'name' FieldDefinitionCollection fields = new FieldDefinitionCollection(); fields.addFieldDefinition(new FieldDefinition("name", BaseTypes.STRING)); service1.setParameters(fields); //Set remote access service1.setLocalOnly(false); //Set return type service1.setResultType(new FieldDefinition(CommonPropertyNames.PROP_RESULT, BaseTypes.STRING)); //Add the service definition to the Virtual Thing this.defineService(service1); //Service1 Definition public String Service1(String name) throws Exception { String result = "Hello " + name; return result; }   Create Data Shapes   Data Shapes must be created using code as seen in GeneratorThing.java as shown below:   // Data Shape definition that is used by the generating going offline event   FieldDefinitionCollection fields = new FieldDefinitionCollection();fields.addFieldDefinition(new FieldDefinition(TYPE_FIELD, BaseTypes.STRING));fields.addFieldDefinition(new FieldDefinition(WATTAGE_FIELD, BaseTypes.STRING));fields.addFieldDefinition(new FieldDefinition(AMPS_FIELD, BaseTypes.NUMBER));fields.addFieldDefinition(new FieldDefinition(VOLTAGE_FIELD, BaseTypes.NUMBER));fields.addFieldDefinition(new FieldDefinition(UP_TIME_FIELD, BaseTypes.NUMBER));fields.addFieldDefinition(new FieldDefinition(STATUS_FIELD, BaseTypes.NUMBER));fields.addFieldDefinition(new FieldDefinition(LOCATION_FIELD, BaseTypes.LOCATION));fields.addFieldDefinition(new FieldDefinition(LAST_SYNC_FIELD, BaseTypes.DATETIME));fields.addFieldDefinition(new FieldDefinition(CONNECTED_SINCE_FIELD, BaseTypes.DATETIME));fields.addFieldDefinition(new FieldDefinition(POWER_LINES_FIELD, BaseTypes.INFOTABLE));defineDataShapeDefinition("GeneratorShape", fields); NOTE: It is possible to create a Data Shape, and then use it in a Service definition within your code as StringIndex property, StringMap Data Shape, and StringMapService Service in SimpleThing.java.     Scan Cycles   To complete the implementation of the VirtualThing class, we recommend you provide an override and implementation to the processScanRequest method. This method provides a universal method for all VirtualThing implementations. This method could be used or a new method could be created for this purpose. The processScanRequest method in VirtualThing.java does not have an implementation of its own. An implementation from DeliveryTruckThing.java can be seen below:   // The processScanRequest is called by the PowerGrid class every scan cycle @Override public void processScanRequest() throws Exception { // Execute the code for this simulation every scan this.scanDevice(); this.updateSubscribedProperties(1000); this.updateSubscribedEvents(1000); }   Bound Properties in Cycle   The scanDevice method in GeneratorThing.java performs a number of tasks from retrieving Property values to firing Events. To retrieve a Property using binding, a request is made to the client using the name of the Property. A good programming practice is to handle how these Properties are accessed and set. Note that the update method for Properties and Events must be used after queueing an Event or setting a Property value. In the example below (used within the Delivery Truck Example), getter and setter methods are used for added control. The getProperty() call is used on the VirtualThing: public Double getSpeed() { return (Double) getProperty("Speed").getValue().getValue(); } public void setSpeed() throws Exception { setProperty("Speed", this.speed); } public Location getLocation() { return (Location) getProperty("Location").getValue().getValue(); } public void setLocation() throws Exception { setProperty("Location", this.location); }     Click here to view Part 4 of this guide.
View full tip
    Step 3: Test Connectivity    Before you can begin developing with the ThingWorx Java SDK, you will need to generate an Application Key and add it to the source code provided.   Generate Application Key On the Home screen of Composer click + New the top left.     In the dropdown list, click Application Key.   Give your Application Key a name (i.e., MyAppKey) and set the Project (ie, PTCDefaultProject). Assign the application key to a User.   Click Save. After saving, a Key ID is generated and appears above the Expiration Date. This is the secret key that you will use to make secure connections. If you have not updated the Expiration Date field, the default will be one day. This is an example of the Application Key ID that you will use for a successfull connection.   NOTE: Using the Application Key for the default Administrator is not recommended. If administrative access is absolutely necessary, create a User and place the user as a member of Admins.   Modify Source File   At the top level, locate the SimpleClient Java source file in a package under the src folder. Open the SimpleClient.java source file and update the URI with the IP address of your ThingWorx instance. For example: config.setUri("ws://127.0.0.1:80/Thingworx/WS");   In the SimpleClient.java source file, update the Application Key with the Application Key you stored from the last section. For example: config.setSecurityClaims(new SamplePasswordCallback(cmd.getOptionValue("b3d06be7-c9e1-4a9c-b967-28cd4c49fa80"))); //SET YOUR APPLICATION KEY HERE     Compile and Run Code   Right-click the SimpleClient.java file. Scroll to Run As then select Java Application.   The output in the Eclipse console will confirm connection and authentication to the ThingWorx platform.     Step 4: Run Sample Applications   The Java code provided in the download is pre-configured to run and connect to the Entities in the ThingWorxEntitiesExport.xml file. Keep track of the IP address of the ThingWorx Composer you are using. Many of the utilized libraries are based on the use of Java 1.8. Use other versions at your own risk.   Within your Eclipse ThingWorx Development project, navigate to the com.thingworx.sdk.examples package and open ExampleClient.java.   The URI structure is as follows: ws://host_name:port_number/Thingworx/WS. Update the host_name and port_number to the host and port of your ThingWorx server. Navigate to the following line and update the IP and port if necessary: config.setUri("ws:// 127.0.0.1:80/Thingworx/WS"); TIP: To enable secure https connection, change “ws” to “wss” and port number to 443. (default port for https is 443). Navigate to the following line in ExampleClient.java and update the value of appKey to the keyId in the “admin_key” Application Key in the ThingWorx Composer. If this connect fails, attempt to use the "admin_key" Application Key in the ThingWorx Composer. Using the default admin's key is not recommended. For future development, create users and add them to be a member of the group of Administrators: config.setSecurityClaims(new SamplePasswordCallback(cmd.getOptionValue("b3d06be7-c9e1-4a9c-b967-28cd4c49fa80"))); //SET YOUR APPLICATION KEY HERE Right-click ExampleClient.java, scroll to Run As, and select Java Application. You should be able to see a new Thing in your Composer called SimpleThing_2.   To check the connected Entities, go to the Monitoring screen.   Click Monitoring. Click Remote Things from the list to see the connection status.   You will now be able to see and select the Entity within the list. NOTE: SimpleThing_1 and SimpleThing_2 will also have an update to the lastConnection property. While SimpleThing_1 is unbound, SimpleThing_2 is bound for the duration of the application run time.     Step 5: Example Client Connection   The Java code provided in the ExampleClient.java file initiates a number of actions from establishing a connection to defining Services and Properties.   Configuration   In the first step of connecting to the platform (Establish Physical Websocket), we create a ClientConfigurator instance to hold the location (URI) needed to point to the websocket of the ThingWorx Composer. It is also used to:   Configure the ThingWorx URI of the server Set the Application Key used for authentication Set the connection reconnection interval Ignore ssl errors ClientConfigurator config = new ClientConfigurator(); config.setUri("ws://127.0.0.1:80/Thingworx/WS");   Authentication   In the second step of connecting to the platform (Authenticate), we provide this ClientConfigurator instance an Application Key that belongs to the default_user that was imported to the ThingWorx Composer. The Application Key must match the keyId value for the User you would want to have the specific control and permissions.   **WARNING: It is not best practice to utilize the Administrator’s Application Keys in Edge development. For the reason that Application Keys in java source code are vulnerable to de-compilation and storing them in a configuration file is dangerous, the best practice is to create new Users, and give them any permission deemed necessary.   config.setSecurityClaims(new SamplePasswordCallback(cmd.getOptionValue("b3d06be7-c9e1-4a9c-b967-28cd4c49fa80"))); //SET YOUR APPLICATION KEY HERE   NOTE: If you are not using SSL/TLS, use this code to test against a server using a self-signed certificate: config.ignoreSSLErrors(true);   Create Client Communication   To create a client with the above configuration, create an instance of ExampleClient and pass the configurator created in the step above. ExampleClient is a class that extends ConnectedThingClient. The ConnectedThingClient facilitates communication to the ThingWorx server as well as manages any contained VirtualThing. ExampleClient.java is an example of this and creates the instance on the line: ExampleClient client = new ExampleClient(config); Create and Bind Thing Before starting the client, it is best to bind all VirtualThings that will be bound in order to decrease the necessary request messages. Binding Things before starting the client creates one bind request message to go to the ThingWorx server with all of the Things included. Starting the client then binding Things creates a bind request for each Thing that is being bound. // Create a new VirtualThing. The name parameter should correspond with the // name of a RemoteThing on the Platform. In this example, the SimpleThing_1 is used. VirtualThing thing = new VirtualThing(ThingName, "A basic virtual thing", client); // Bind the VirtualThing to the client. This will tell the Platform that // the RemoteThing 'SimpleThing_1' is now connected and that it is ready to // receive requests. client.bindThing(thing);   Start Connection   You can now start the client, which will establish the AlwaysOn protocol with the ThingWorx Composer. This protocol provides bi-directional communication between the ThingWorx Composer and the running client application.   // Start the client. The client will connect to the server and authenticate // using the ApplicationKey specified above. client.start();       Click here to view Part 3 of this guide.    
View full tip
  Use our developer toolkit to connect Java-enabled devices and build an application.     GUIDE CONCEPT This project will introduce complex aspects of the ThingWorx Java SDK and help you to get started with development.   Following the steps in this guide, you will develop your own IoT application with the ThingWorx Java SDK.   We will teach you how to use the Java programming language to connect and build IoT applications to be used with the ThingWorx Platform.   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete all parts of this guide is 60 minutes.     YOU'LL LEARN HOW TO   Establish and manage a secure connection with a ThingWorx server, including SSL negotiation and connection maintenance Enable easy programmatic interaction with the Properties, Services, and Events that are exposed by Entities running on a ThingWorx server Create applications that can be directly used with your device running the Java programming language Basic concepts of the Java Edge SDK How to use the Java Edge API to build a real-world application How to utilize resources provided in the Edge SDK to help create your own application   Step 1: Completed Example   Download the Java_SDK_Extra_Samples.zip attached to this article and extract the contents.   In this tutorial we walk you through a real-world scenario for a power grid network. The Java_SDK_Extra_Files.zip file provided to you contains the following files and Entities as a completed version of the scenario we will cover. Please keep in mind, the Java SDK can also be utilized for Android development and general Java development.   Name Description PowerGrid Source code for an extensive example of a power grid network Delivery Truck Source code for the delivery truck application ExampleClient Source code for examples on how to do different tasks FileTransfer Source code for a file transfer application Tunneling Source code for a tunneling application SimpleThing Source code for simple connections and examples SteamSensor Source code for a steam sensor that provides configuration during runtime   Once you complete your Java environment setup and import the JavaExampleEntities.xml file into ThingWorx Composer, you will be able to utilize these Entities:   Feature Entity Type Description  Generator1  Thing  Used with the power grid edge example  Generator2  Thing  Used with the power grid edge example  Generator3  Thing  Used with the power grid edge example  Consumer1  Thing  Used with the power grid edge example  Consumer2  Thing  Used with the power grid edge example  Consumer3  Thing  Used with the power grid edge example DeliveryTruck_1 Thing Used with the delivery truck edge example DeliveryTruck_2 Thing Used with the delivery truck edge example DeliveryTruck_3 Thing Used with the delivery truck edge example FileTransferExample Thing Used with the file transfer edge example TunnelExample Thing Used with the tunnel edge example SimpleThing_1 Thing Used as a simple edge example for coding and connectivity SimpleDataShape Data Shape Used as a simple edge Data Shape example for coding and connectivity DeliveryTruckShape Data Shape Used as a Data Shape with the delivery truck edge example EdgeExample Model Tag Used as a Model Tag for tagging all entities; enables quicker searches DeliveryTable Data Table Used as a Data Table with the delivery truck edge example Default_user User User created to be used with the SDK examples PTC Organization An Organization that helps with security in edge examples Admin_key Application Key An Application Key used for the Admin Default_key Application Key An Application Key used for the Default User; this is the recommended key to use   Step 2: Environment Setup   You can use the Java SDK with any IDE of your choice. The steps below demonstrate how to use the Eclipse IDE as an example.   If you have not already done so, install a Java Development Kit (JDK) from Corretto or OpenJDK in order to compile and run Java code and download the ThingWorx Java SDK. The download will include the JARs necessary to run the SDK.   The Eclipse Java IDE is a centralized location to store the code, resources, and files utilized by this guide. Download and install the latest Eclipse Java IDE from the Eclipse website.   Create Java Project   When the Eclipse Welcome window appears, click Create a new Java Project. In the New Java Project setup wizard, enter ThingWorx Development as the project name. Java 1.8 is the supported and recommended JDK.   Click Finish.    Set Up User Library   Right click the newly created ThingWorx Development project in the Package Explorer. Expand the Build Path selection and select Add Libraries.  Click User Library. Click Next.  Click User Libraries. Click New, enter ThingWorx Java SDK as the library name. Click OK.   Set Up Javadoc   With the ThingWorx Java SDK selected, click the Add External JARs button.       In the pop-up window, navigate to the location in which you unzipped the ThingWorx Java Edge SDK. Navigate to the lib folder, select all of the JARs, then click Open. Within the ThingWorx Java SDK library, expand the thingworx-common-xxxx.jar folder and select Javadoc location. Click Edit. Select the Javadoc in archive and External file radio buttons, then click Browse. In the pop-up window, navigate to the location in which you unzipped the ThingWorx Java Edge SDK. Navigate to the lib folder, highlight the thingworx-java-sdk JavaDoc JAR File, then click Open. Click OK. Repeat steps 1-8 for the thingworx-communications-client JAR’s Javadoc location field shown in step 10. Confirm that your setup looks like this:   Click OK. Select the checkbox for the ThingWorx Java SDK library, then click Finish.   Import Sample Files   Right click the ThingWorx Development project and click Import.   In the Import wizard, type File System into the filter. Click Next.     In the pop-up window, navigate to the location in which you unzipped the ThingWorx Java Edge SDK. Navigate inside the samples folder and select the src folder.     Click OK. Select the checkbox for the src folder, then click Browse.     Type ThingWorx Development/src into the text box.   Click OK. Click Finish.     Expand the ThingWorx Development project.       Click here to view Part 2 of this guide.
View full tip
  Step 7: Import Extension   In the ThingWorx Composer. in the bottom left, click Import/Export, then select Import.   NOTE: The build produces a zip file in AuthenticatorExample->build->distributions folder. This zip file will be required for importing the extension.          2. For the Import Option field, select Extension.            3. Click Browse and choose the zip file in the distributions folder (located in the Eclipse Project's build directory).       4. Click Import to finalize the import.   Navigate to New Authenticator   Navigate to and select Security > Authenticators.            2. You will now see your CustomizedAuthenticator Authenticator as a option to view/edit.            3. Click Edit or View to see this new Authenticator. You wil notice the priority is 1.   Troubleshooting   If your import did not get through with the two green checks, you may want to modify your metadata.xml or java code to fix it depending on the error shown in the logs.     Issue Solution JAR Conflict arises between two similar jars JAR conflicts arise when a similar jar is already present in the Composer database. Try to remove the respective jar resources from the metadata.xml. Add these jars explicitly in twx-lib folder in the project folder inside the workspace directory. Now, build the project and import the extension in ThingWorx Composer once again. JAR is missing Add the respective jar resource in metadata.xml using the ThingWorx->New Jar Resource. Now, build the project and import the extension in ThingWorx Composer once again. Minimum Thingworx Version [ 7.2.1] requirements are not met because current version is: 7.1.3 The version of SDK you have used to build your extension is higher than the version of the ThingWorx Composer you are testing against. You can manually edit the configfiles->metadata.xml file to change the Minimum ThingWorx version to your ThingWorx Composer version.     Step 8: Integrating Custom Authentication   Integration can be handled in different methods based on your security needs and architecture. The Authenticator we created works with the demo site we provided in the download.   Create ThingWorx User   Let's create the User that we will be processing login attempts.   In the ThingWorx Composer, click the + at the top left of the screen.   Select User in the dropdown.   Set the Project (ie, PTCDefaultProject) and enter the Name for this new user as TwxUser. Enter the Password for the new user to something easy to remember (ie, 2020Password2021).   Click Save.   Create Logger   Create a helpful logger for authentication attempts.   Create a Thing named AuthenticationStamper to go with the LoginHelper variable in the earlier Java source code. Ensure this new Thing inherits from the RemoteThing Match the properties for the AuthenticationStamper with the two properties in the below image.   Save the changes.   Create Login Helper   Create a stream for authentication attempts for helpful tracking. Create a ValueStream named AuthenticationStream and Save the Entity. In the Properties and Alerts section of the ValueStream, click Manage Bindings.   Setup the binding to match the below configurations. Bind the properties to the AuthenticationStamper Thing.   Save the changes made to the ValueStream.   Demo Page Login   With a browser, open the TestSite.html web page found in the Demo directory of the download. You should see a login page similar to that as the below image.   Enter the name of the user we created, TwxUser. Enter the password for the user. We suggested setting this to Password2019. Click Submit. You will now be authenticated and logged in.     Step 9: Next Steps   Congratulations! You've successfully completed the Create An Authentication Extension tutorial, and learned how to:   Install the Eclipse Plugin and Extension SDK Create and configure an Extension project Create Authentication Application 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 Support Extension Development Guide    
View full tip
  Connect IoT data from devices to Widgets that display in your application UI.   GUIDE CONCEPT   This project will demonstrate how to bind a data source to a Widget.   Following the steps in this guide, you will be able to show state-based changes resulting from data updates.   We will teach you how to essentially connect your backend data to the Widgets in your Mashup. ThingWorx facilitates this process with built-in functionality.     YOU'LL LEARN HOW TO   Bind data to Widgets in ThingWorx Mashup   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes.      Step 1: Completed Examples    Download the Complete Data Binding Example using file BindDataEntities.zip attached to this guide. Within this file you, 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: Bind Data to Widget   In order to display data from connected devices, each Widget must be connected to a data source. You should already be familiar with how to find the Widgets in the top left panel of a Mashup screen.   Mashup Areas   In the top right of the screen in a Mashup Entity is the Data Panel. This is where Entities and Services are used to bring in data and added functionality. This area also includes the Session Tab, which includes data that is being stored in the session. You can learn more about that in the Create Session Parameters guide. You can also filter for specific Properties.       In the lower right of the screen in a Mashup Entity is the Data Properties Panel. This is where you can configure how your Service calls will react to different Events. For example, you might want to perform a call to a Service as soon as another Service call is complete. You'll do that in this section. You will also notice the Functions Tab. This table enables you to create custom functionality for you Mashup and Widgets, such as navigating to a different Mashup on the click of a button.       In the lower left of the screen in a Mashup Entity is the Widget Properties Panel. This is where you'll be able to not only customize your Widget, but connect data directly from Services and other Widgets. You will also notice the Style Properties Tab. This will provide access to change the styling and themes used for a Widget. You can also filter for specific Properties.       In the bottom middle of your screen, you'll notice the Bindings Panel. This panel shows you where your connections are in reference to Widgets, Services, and any Events that are being used to connect them. Whenever you have a problem with thinking about the flow of your Mashup, look down to this panel to get a quick idea. You'll also notice the Reminder Tab in this area. This tab just helps with things you might have forgotten to do when setting up your data binding, such as setting the display field for a Widget.       Let's now move forward with setting up our data binding.    Add Service   Open the HelloWorldPlayground Mashup. Drag and drop the Grid Advanced Widget to the left-hand column of your Canvas.      NOTE: If a pop-up appears about adding a Panel, choose Yes. 2. Click + in the Data panel.       3. Search and select the HelloWorldData Data Table from the search bar in the top left of the home screen. 4. Search for the GetFirstEntry Service and click the blue arrow. The GetFirstEntry service is part of the DataMagicians.XML file you imported.   5. Check the Execute on Load checkbox. This makes the page automatically load with content for a Widget. 6. Click Done.     Bind Data to Widget   We will bind data to a Widget, but also make the Widget editable. When it comes to making the field Editable, keep in mind any connections or Entities involved. In this case, the World field is attached to an Entity.   In the Data panel, expand the Returned Data section. Drag and drop the All Data field of the GetFirstEntry Service to the Grid Advanced Widget. A pop-up will appear to select the binding target, select Data.   In the Widget Properties panel, check the checkbox for IsEditable. This will allow users to edit the data in the Property fields. Select the Configure (Gear) button. The Configure Grid Columns window will open.   Update any fields you would like hidden (for instance, uncheck the box next to timestamp and key).     Click on source field. Check the Editable checkbox at the bottom.   Click Done to close the pop-up.   Data Panel Buttons   There is an assortment of helpful buttons in the Data panel to make our lives easier.     Top Row of Buttons   The + button that you used before adds more Entities as a resource to make Service calls. The circlular button next to it provides a reload functionality. This is useful when you've made a change to a Service and would like for it to appear here. For example, adding a new parameter to a Service call.   Buttons by Entity   The i button provides information and access to the Entity in question. The Add Service button adds a Service that belongs to the same Entity. This will definitely help with saving time. The last button is the Delete button. This will delete the Entity from the list of resources that can make Service calls.   Buttons By Service   The only button is the Delete button. This will delete the Service from the list of Service calls an Entity has available.   Adding More Functionality   Click the Add Service button on the HelloWorldData Entity in the Data pane.     Search for the UpdateDataTableEntry Service and click the arrow to select it. Leave the Execute on Load checkbox unchecked and click Done. Deselect the Execute on Load option if you would like the page to load with content in response to user input, rather than automatically at startup. Click on the UpdateDataTableEntry Service, then click on the Data Binding button in the bottom right. Click the arrow next to the Values Property under Parameters. Click Add Source. When the list of Widgets appear, click on the Editedtable of the Grid Advanced Widget that we added. Click Next and Done. Select the Grid Advanced Widget on your canvas. Drag and drop the EditCellCompelted property onto the UpdateDataTableEntry service.     NOTE: The columns returned by a data service are shown under the All Data section of the data service. They are outbound bindable, indicated by the outward facing arrows. When a data service All Data or individual column is bound, the arrows become filled in. You can also bind the data from one Widget to another.         8. Click Save and View Mashup.   You have just bound data from a service to a Widget. There are many different Widgets, and the process for binding data to a Widget is often similar. Within Composer, you can simply drag and drop to bind configurations for Events and Properties.     TIP: As, an extension to this lesson, edit the Property Display Widget to update the entry in the HelloWorldData DataTable. Editing the name of the World will result in no entries being updated. To add or update an entry when you update the Name property, used the AddOrUpdateDataTableEntry service instead of UpdateDataTableEntry.     Step 3: Next Steps    If you have questions, issues, or need additional information, refer to:   Resource Link     Community Developer Community Forum Support Help Center
View full tip
  Step 9: File Transfer Example   To handle file transfers, a virtual directory is created in the SteamSensor1 entity and in the [C SDK HOME DIR]/examples/FileTransferExample application directory. The source code used for this example is found in [C SDK HOME DIR]/examples/FileTransferExample/src/main.c.   Inside of the [C SDK HOME DIR]/examples/FileTransferExample folder, create the folder structure shown below:   /transfer/ /transfer/incoming/ /transfer/outgoing/   Inside of the /transfer/outgoing/ directory, create and open a file with the name outgoing.txt. Once the outgoing.txt document is open, add the following text, save, and close the file: Hello. This is a file coming from the client application. Navigate to the [C SDK HOME DIR]/examples/FileTransferExample/src/main.c code and update the lines below with the appropriate information for your IP, port, and the “admin_key” Application Key’s keyId value in the ThingWorx Composer:   /* Server Details */ #define TW_HOST "127.0.0.1" #define TW_PORT 80 #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c"   To support file transfers in your client application, you must use the   twFileManager_AddVirtualDir function in order to create the virtual directories in the entity with such a capability. It will also define the directories available for file operations. A virtual directory maps a unique name to an absolute path of a directory in the file system. All subdirectories of the specified directory are exposed to the server. You can define multiple virtual directories. The directories do not need to be contiguous. Staging Directory   As an optional, but recommended step, you should set the directory that the application should use for staging when performing file transfers. This can be seen in the line below and should be done before initializing the FileManager. The default directory of the FileManager is most likely owned by root and will require a change to either the location of the staging directory and the ownership of the staging directory, or running the application as a User with the correct permissions.   twcfg.file_xfer_staging_dir = "staging";   The example provided uses the TW_SHARE_DIRECTORY macro to create two virtual directories that will act as the root directories in the virtual file system of this application are added. The client is then started as follows with the necessary TW_ADD_FILE_TRANSFER_SHAPE function being called:   TW_ADD_FILE_TRANSFER_SHAPE(); TW_SHARE_DIRECTORY("in", "/transfer/incoming/"); TW_SHARE_DIRECTORY("out", "/transfer/outgoing/");   The creations of the payloads used to create the remote directories on the platform have been moved to a helper function below to make the design cleaner:   int setupSystemRepo(const char * remoteInPath, const char * remoteOutPath, const char * remoteFile);   After our remote directories and files have been setup, it is time to perform the file transfers. Normally, this would mean invoking the Copy service for a Subsystem, but two functions have been created to make this process easier:   int twFileManager_GetFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid) int twFileManager_SendFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid)   The table below displays an example of the first set of parameters:   Parameter Example Description sourceRepo SystemRepository The name of FileRepository or RemoteThing to transfer the file FROM. sourcePath outgoing The path specifying the location of the source file. sourceFile The name of the source file.   targetRepo SteamSensor1 The name of FileRepository or RemoteThing to transfer the file TO. targetPath incoming The path specifying the destination location of the file. targetFile incoming.txt The name of the file at the target. This name can differ from the sourceName. timeout 15,000 The amount of time (in seconds) to wait for a synchronous transfer to complete before cancelling the transfer. async false If false, the service call will block for timeout seconds or until the transfer completes. tid incoming0123 The unique TID associated with the file.   The C SDK also provides the ability to create a FileCallback function that the FileManager will call that function when any file transfer events occur. You can provide a wildcard filter so that only file transfer Events of files that match the filter call the callback function. In addition, callbacks can be set up as “one-shots” such that the callback is unregistered automatically after it is invoked the first time.   NOTE: An optional file transfer callback is registered in the code and provided. You will see the output from the function as files are sent and received.   After running this application, you will notice a new file in the transfer/incoming folder after refreshing. This is the file that we created in the ThingWorx Composer file system for the SystemRepository Entity and was able to copy from that location to our local project. We have also sent a file to the server’s SystemRepository. The BrowseFileSystem and GetFileListing services can be used to check for the folders and files created.   twFileManager_RegisterFileCallback(fileCallbackFunc, NULL, FALSE, NULL);     Step 10: Support Other Platforms   All Websocket errors indicate some general issue communicating with the ThingWorx platform. If you experience an issue connecting, refer to the table below for a list of websocket errors, their corresponding codes, and an explanation of the issue.   Code Message Troubleshooting 200 TW_UNKNOWN_WEBSOCKET_ERROR An unknown error occurred on the websocket. 201 TW_ERROR_INITIALIZING_WEBSOCKET An error occurred while initializing the websocket. Check your websocket configuration parameters for validity. 202 TW_TIMEOUT_INITIALIZING_WEBSOCKET A timeout occurred while initializing the websocket. Check the status of the connection to ThingWorx. 203 TW_WEBSOCKET_NOT_CONNECTED The websocket is not connected to ThingWorx. The requested operation cannot be performed. 204 TW_ERROR_PARSING_WEBSOCKET_DATA An error occurred while parsing websocket data. The parser could not break down the data from the websocket. 205 TW_ERROR_READING_FROM_WEBSOCKET An error occurred while reading data from the websocket. Retry the read operation. If necessary, resend the data. 206 TW_WEBSOCKET_FRAME_TOO_LARGE The SDK is attempting to send a websocket frame that is too large. The Maximum Frame Size is set when calling twAPI_Initialize and should always be set to the Message Chunk Size (twcfg.message_chunk_size). 207 TW_INVALID_WEBSOCKET_FRAME_TYPE The type of the frame coming in over the websocket is invalid. 208 TW_WEBSOCKET_MSG_TOO_LARGE The application is attempting to send a message that has been broken up in to chunks that are too large to fit in a frame. You should not see this error. 209 TW_ERROR_WRITING_TO_WEBSOCKET An error occurred while writing to the Web socket. 210 TW_INVALID_ACCEPT_KEY The Accept key sent earlier from ThingWorx is not valid.     Step 11: Next Steps   Congratulations! You've successfully completed the C SDK Tutorial, and learned how to utilize the resources provided in the Edge SDK to create your own application.   Learn More   We recommend the following resources to continue your learning experience:   Capability Link Build Design Your Data Model Build Implement Services, Events, and Subscriptions   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support C Edge SDK Help Center    
View full tip
  Build a Predictive Analytics Model - Video Guide   This project will introduce ThingWorx Analytics Builder via a convenient video-guide. Following the steps in this video, you will create an analytical model, and then refine it based on further information from the Analytics platform. We will teach you how to determine whether or not a model is accurate and how you can optimize both your data inputs and the model itself.     ThingWorx Analytics Server Installation with SSL   This video demonstrates the installation of Analytics Server with SSL protections enabled. It includes information about generating the necessary certificates and truststores to enable SSL for each component that connects with the server.     ThingWorx Platform Analytics Installation with SSL   This video demonstrates the Platform Analytics installation with SSL protections enabled. It provides information about generating the necessary certificates and truststores to enable SSL for all connected components, including RabbitMQ and Flink.     Toolbar Widget | ThingWorx 9   Watch this video to learn how to add a Toolbar widget to a mashup in ThingWorx. You'll learn how to define actions using a data service and create bindings to control and configure a Grid widget.     ThingWorx SSO: Login demonstration from Azure AD to ThingWorx   This video demonstrates the ThingWorx SSO login procedure using Azure AD. The login procedure is shown from a user point of view. Then a behind the scenes view looks at the design in ThingWorx Composer.     Menu Bar Widget ThingWorx 9   Watch this video to learn how to create a mashup layout that uses a Menu Bar widget for navigation. You'll learn how to create a layout, define menu items, and configure the widget.     ThingWorx AD FS SSO Setup   This video provides a walk-through of the steps required to set up SSO for ThingWorx in an environment where AD FS is both the CAS and the IdP. The focus is on the AD FS setup steps.     Create Your Application UI   Following the steps in this video-guide, you will learn how to use the ThingWorx Mashup Builder tool to create a Graphical User Interface (GUI) for your IoT Application. We will teach you how to rapidly create and update a Mashup, which is a custom visualization built to display data from devices according to your application's business and technical requirement     Get Started with ThingWorx for IoT   Explore the ThingWorx Foundation Internet-of-Things application building platform in a convenient, instructional video guide format.     Thingworx Mashup 101 - Do's and Don'ts   This session covers the most common and useful tips about how to correctly use Mashup builder, Widgets and Layouts – and what to avoid - to create applications with good principles of UI/UX and easier to maintain.     What's New in ThingWorx 9.1   The industry’s most complete IIoT platform just got better. Loaded with a full range of new and updated features and functionality, you can expect powerful platform capability enhancements across the board.       Standardize Connectivity to Devices, Applications, & Systems for Centralized IIot Data   You can’t implement IIoT solutions if you can’t connect to your assets, but in complex environments connectivity can seem like an insurmountable challenge. ThingWorx makes it easy to establish standardized connectivity, so you can create a secure, single-source for accessing industrial data across your IT and OT systems     Bar Chart Widget | ThingWorx 9   Watch the following video on how to add the Bar Chart widget to a mashup and configure basic widget properties.     Button Widget | ThingWorx 9   Watch the this video to learn how to add the Button widget to a mashup and use its Clicked event to trigger data services.     Line Chart Widget | ThingWorx 9   Watch the this video to learn how to add the Line Chart widget to a mashup and bind a data source.     ReImagine Your Application UI With Collection and Custom CSS   Create compelling, modern application user interfaces in ThingWorx with the latest enhancements to our Mashup visualization platform - Collection and Custom CSS. In this webinar with IoT application designer Gabriel Bucur, we'll show how the new Collection widget makes it easy to replicate visual content in your UI for menu systems, dashboards, tables, and more.     Testing Your Edge Application   Native testing is an often-overlooked aspect of edge application development. This session shares how to perform thorough testing before you push your application into live production.     Predictive Maintenance with Thingworx 101   Adopting a predictive maintenance strategy for the first time can often feel daunting, but it doesn't have to. Learn how ThingWorx can be used to leverage edge devices and turn monitoring activity into action.     ThingWorx Mashup Pitfalls: What to Avoid and What Not to Do   Designing Mashups takes time. Moreover, expanding upon a Mashup that was built for a small-scale application can get cumbersome.     IoT Security: Keeping Devices Safe in a High Risk World   Understanding access controls can be difficult. With the built-in security features and concepts in ThingWorx, you can easily give your devices access on-demand.     Edge Connectivity in Unreliable Networks   The Store and Forward feature within ThingWorx Industrial Connectivity assures users that critical data collected at the edge won't get lost during an outage.  
View full tip
    Use ThingWorx Advisors to view trends and monitor Alerts.     GUIDE CONCEPT   The intent of this guide is to provide instructions to configure trends and alerts in the ThingWorx Advisors.   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete all parts of this guide is 30 minutes.     YOU'LL LEARN HOW TO   In this guide, you will learn how to: Configure and view trends in machine performance Create and configure an alert Monitor an alert   Step 1: Configure and View Trends  To begin, you will learn how to open up ThingWorx Advisors.   In ThingWorx Foundation Composer, click Browse then Visualization > Master then click PTC.Factory.PlantStatus.Master.          2. Next click the View Mashup button.                 3. Click the Utility Selector grid in the upper left            4. Click Trending and Troubleshooting              5. Click the + icon.               NOTE : A New Trend pop-up will appear.        6. In the Trend Name text box, type Station A Temperature, then click OK.              7. In the Tags area, click the + icon to start plotting a tag             8. In the Equipment Type drop-down, choose KEPServerEX, in the Equipment drop-down,        choose your KEPServer or the simulation server.          9. In the Server Structure menu, click LineGroup1 and use the drop-down menu to select LineGroup1.1-3_CNCMill. In the Tags menu area, click Temperature then click OK, or choose a tag based on your KepServer configuration.   10. Review the trend data for Station A.     11.  Repeat these steps to apply additional property setting to Station A.   12. Check the Show Value Range box in the Tags area. Review the trend data for the properties selected.                      NOTE: The three selected tags will appear plotted in the Show Value Range table.     Click here to view Part 2 of the guide.  
View full tip
Announcements