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

ThingWorx Navigate is now Windchill Navigate Learn More

IoT & Connectivity Tips

Sort by:
  Learn how to create or update your system to be more secure   GUIDE CONCEPT   ThingWorx allows for a layer of security within your company or organization to be utilized for authentication and 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 and configure ThingWorx to perform your security needs.   YOU'LL LEARN HOW TO   Securing data and private information Use services, alerts, and subscriptions to handle processes without human interaction Handling group and organization permissions   NOTE:  The estimated time to complete this guide is 60 minutes.     Step 1: Examples and Strategy   Download the attached FoodIndustry.zip users and extract/import the contents. These are to be used as you work through this learning path. For the completed example, download FoodIndustryComplete.zip.   In this tutorial we continue with our real-world scenario for the Fizos food company. We already have our factory data, automated cooking processed for our sausage product lines, and an automated process for picking up and delivering goods. What we need now is to ensure our organization, security groups, and data is truly secure. Having security permissions at each level and each type of entity involved with our company enables us to have full control over every aspect.   Setting Up Organizations   Organizations are hierarchical structures that allow the user to assign visibility to entities in the ThingWorx Model. This model provides the top down structure from the highest level in an organization or department, to the lower levels of said entity. Each level within this structure also allows for users and groups to be added. This provides a greater level of customization to resources within the ThingWorx Composer.   We will not only create an organization that represents Fizos, but we will have membership in the organization to represent partners, external users, guests, etc. With this level of granularity, we have more control over what is happening at each level.   In the ThingWorx Composer, click the + New at the top of the screen.   Select Organization in the dropdown. Name your Organization Fizos.  Set the Project field (ie, PTCDefaultProject). Click Save   Select the Organization tab to see the hierarchy. Select Unit 1 in the middle of the canvas. Update the Name field to Company and save your changes.   Create Additional Organization Units   Now let's add a node for Employees, Interfaces(APIs), Partners, Customers, Guests, and other groups we might consider important.   Click the green + under the structure you would like to expand. Name your Organization unit Employees. Click Save. We won't add groups as yet. We will do that in the following sections.   Repeat the steps to create the full top level units. It should look similar to the following: We now have the starting structures for Fizos. Next, we will need to add security groups and more units.       Step 2: Creating Security Groups   In many IoT solutions there will be a large scale of users using the system. Because of this it doesn’t make sense to manually set the permissions of every user added to the system. This is why we created User Groups. User Groups provide a role-based approach to permissions and exist to give similar users the same permissions across multiple entities on the platform. User groups set permissions exactly the same way as users do (see next section), but you can simply add a user to a user group in order to set permissions at scale.   Creating a user group such as Fizos.External.SecurityGroup would allow you to have a group with no design time permissions, but allow run time permissions for specific aspects of your solution such as reading product pricing from a service. Similarly you could create a user group called Fizos.Developers.SecurityGroup (under the Employees unit) who would have design time and run time permissions to work on your solution.   Create Security Groups   In the ThingWorx Composer, click the + New at the top of the screen.   Select User Group in the dropdown. Name your group Fizos.Partners.SecurityGroup. Set the Project field with an existing Project (ie, PTCDefaultProject). Click Save.   Repeat these steps to create more user groups for each of the top level units we created in the last section (Customers, External, Interfaces, Employees). We can also add in some groups from the companies we listed as customers and partners earlier in this learning path. Below is an example of all the groups I created for this example:   NOTE: Individual user permissions will override group user permissions. In other words, if you initially add a user to a group so they inherit the permissions of the group, you will still be able to customize permissions for an individual user in that group as needed.   Default User Groups   The platform has a few user groups included in the platform by default. These are used to set up common roles that are often associated with using the platform and have built in permissions. These groups are not meant to be used when creating new applications or general permissions.   Step 3: Configuring Permissions   These permissions can be accessed on any entity created on the platform. All entities have permission control for both design time and run time. Permission Time Control Design time Controls what users are able to do with entities themselves while building the solution. Run time Controls what the users are able to do with the data for an entity when they use the solution. Permission Type Description Property Read Read property values Property Write Update property values Service Execute Execute Services in this Entity Event Execute Queue or fire Events in this Entity Event Subscribe Ability to subscribe to Events in this Entity Access Type Description Allow Allow the user's access to this feature. Deny Deny the user's access to this feature. Inherit Set the user's access to this feature based on permissions in Entities this Entity is based on or the configurations at a higher level.   Add Permissions for an Entity   Once an entity has been selected for editing, select the Permissions tab. Based on what you would like to edit, select the Design Time or Run Time tab.   The All Properties, Services, and Events section provides blanket security to all of these features for a group or user. The Property, Service, or Event Overrides section is used for any overrides that need to be made for specific features.   In the example blow, the User a.jones has the ability to read properties, fire events, and subscribe to events. The User does not have the ability to update a property or execute a Service. In the second section, a.jones is allowed to call the GetConfigurationTable Service (even though he was restricted from doing so in the other section).   To set a permission, filter and select a User/User Group. When their name is in the table, click the Permission Type you would like for this Entity. Default permissions are added to the User or User Group you filtered and selected. This will be full access permissions unless you've changed one of the fields.   Bulk Permissions Handling   When you would like to set the permissions to an entity in bulk, ie permissions for all Things, you can use the Collections option.   On the left hand side, click the lock. Click the Collections option under Permissions. Select the checkbox next to Things. Click Edit Permissions button. Now you will see the same interface you used above, except this time, it will be for all Things instead of a singular entity. You can use these permission settings to stop access to all of the entities you would not want an external user being able to see.   Bulk Permissions Reporting   When you would like to verify the permissions to an entity, ie permissions for all Fizos.Logistics, you can use the Access Report option.   On the left hand side, click the lock. Click the Access Report option under Permissions. Set the User or User Group. (in this case Fizos.VizosMeatMarket.SecurityGroup) Set the Entity (in this case Fizos.Logistics) Click Apply.     You will be able to see what this User Group has access to as it pertains to the Fizos.Logistics Entity. Try other Entities and User Groups.   Step 4: Next Steps   Congratulations! You've successfully completed the Securing Industry Data guide. In this guide, you learned how to:   Securing data and private information Use services, alerts, and subscriptions to handle processes without human interaction Handling group and organization permissions   If you wish to return to the learning path, click Complex and Automatic Food and Beverage Systems Learning Path   Learn More   We recommend the following resources to continue your learning experience: Capability Guide Build ThingWorx Solutions in Food Industry Build Design Your Data Model Build Implement Services, Events, and Subscriptions   Additional Resources   If you have questions, issues, or need additional information, refer to: Resource Link Community Developer Community Forum  
View full tip
  Learn how to connect ThingWorx Kepware Server to Foundation.   Guide Concept   This guide will teach you how to create a backend Data Model in ThingWorx Foundation that works with ThingWorx Kepware Server to collect data from an Allen-Bradley PLC and send it to ThingWorx Foundation.   You'll learn how to   Create a Data Model in ThingWorx Foundation that accepts information from ThingWorx Kepware Server   NOTE:  The estimated time to complete this guide is 30 minutes       Step 1: Learning Path Overview   Assuming you are using this guide as part of the Rockwell Automation Learning Path, then you have now completed each of the following installations:   Connected Components Workbench ThingWorx Kepware Server ThingWorx Foundation (for Windows)   You’ve also connected an Allen-Bradley PLC to Connected Components Workbench and then to ThingWorx Kepware Server.   In this guide, we’ll propagate that information further from ThingWorx Kepware Server into ThingWorx Foundation.     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 Composer, click Browse. On the left, click MODELING -> Things.   Click + NEW. In the Name field, enter IndConn_Server, including matching capitalization. In the Description field, enter an appropriate description, such as Industrial Gateway Thing to connect to ThingWorx Kepware Server.   If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. In the Base Thing Template field, enter indus, then select the IndustrialGateway Thing template from the sorted list. Click Save.     Step 3: Connect to Foundation   Now that you’ve created an Industrial Gateway 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.   In the Property Editor pop-up, click ThingWorx. In the Enable field, select Yes from the drop-down. In the Host field, enter the IP address of your ThingWorx Foundation server. Enter the Port number. If you are using the “hosted” Developer Portal trial, enter 443.   In the Application Key field, copy and paste the Application Key you just created. In the Trust self-signed certificates field, select Yes from the drop-down. In the Trust all certificates field, select Yes from the drop-down. In the Disable encryption field, select No from the drop-down if you are using a secure port. Select Yes if you are using an http port. Type IndConn_Server in the Thing Name field, including matching capitalization. If you are connecting with a remote instance of ThingWorx Foundation and you expect any breaks or latency in your connection, enable Store and Forward. Click Apply in the pop-up. Click Ok. In the ThingWorx Kepware Server Event window at the bottom, you should see a message indicating Connected to ThingWorx.   NOTE: If you do not see the “Connected” message, repeat the steps above, ensuring that all information is correct. In particular, check the Host, Port, and Thing name fields for errors.     Step 4: Bind Industrial Tag   Now that you’ve established a connection, you can use ThingWorx Foundation to inspect all available information in ThingWorx Kepware Server.   This step will create a new Thing in ThingWorx Foundation representing two output coils of the PLC.   Create Thing for PLC coils   In ThingWorx Foundation Composer, on the left, click MODELING -> Industrial Connections, then click IndConn_Server.   At the top, click Discover. Expand Channel2, then click myPLC. Select check-boxes next to Coil2 and Coil3, then click Bind to New Entity.   Scroll to select RemoteThing, then click OK.   Enter the name PLCcoils, If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. then click Save.   Test ThingWorx Foundation to PLC Communication   Click the Properties and Alerts tab. Confirm that the isConnected Property has a check in the Value field, indicating a good connection between ThingWorx Kepware Server and the PLC. Click the pencil icon in the Coil3 line to open the edit panel, click the True radio button, then click the save checkmark button.   You should here a soft click from the PLC and the Output 3 indicator will illuminate. ThingWorx Foundation is now controlling the PLC through its connection to ThingWorx Kepware Server.     Step 5: Troubleshooting   If the connection to the PLC stops working and there is a Thumbs Down icon next to your properties, the ThingWorx Kepware Server trial edition drivers are not connected to your PLC. The trial edition stops running after 2 hours and must be stopped and restarted. Right-click on ThingWorx Kepware Server icon in system tray.   Click Stop Runtime service. Wait a minute for the process to stop, then click Start Runtime service. If Connected Components Workbench does not connect to PLC, check the IP address of the PLC using RS Linx Classic software that was installed as part of Connected Components Workbench. RS Linx Classic is located Start > All Programs > Rockwell Software > RSLinx > RSLinx Classic Click AB_ETHIP-1, Ethernet and IP addresses of connected PLCs will be discovered NOTE: A changed PLC IP Address (typically seen through Connected Components Workbench) will require an IP Address change in ThingWorx Kepware Server settings.       Step 6: Next Steps   Congratulations! You've successfully completed the Model an Allen-Bradley PLC guide. You've learned how to:   Create a data model that can accept information from ThingWorx Kepware Server Connect ThingWorx Kepware Server to Foundation   The next guide in the Using an Allen-Bradley PLC with ThingWorx learning path is Visualize an Allen-Bradley PLC.   Learn More     Capability      Resource Analyze Monitor an SMT Assembly Line   Additional Resources   For additional information on ThingWorx Kepware Server:     Resource              Link Documentation Kepware documentation Support Kepware Support site
View full tip
  Explore the ThingWorx Foundation IoT application-building platform in a convenient video format.     Guide Concept   This project will introduce you to the principles of ThingWorx Foundation by creating a working web application, guided by a convenient video.   Following the steps in this guide, you will create the building blocks of your first application for the Internet of Things (IoT). You will use ThingWorx Composer to create Thing Templates, which are then used to create Things that model the application domain. A simulator is imported to generate time-series data that is saved to a Value Stream.   After modeling the application in ThingWorx Composer, you'll use Mashup Builder to create the web application Graphical User Interface (GUI).   You'll learn how to   Create a Thing Shape, Thing Template, and Thing Store data in a Value Stream Download and install a data simulator Create an application UI    NOTE:  The estimated time to complete this guide is 30 minutes     Step 1: Video   Click the link below to enjoy the video.   Get Started with ThingWorx for IoT       Step 2: Next Steps   Congratulations! You've successfully completed the Get Started with ThingWorx for IoT Video Guide, and learned how to:   Use Composer to create a Thing based on Thing Shapes and Thing Templates Store Property change history in a Value Stream Define application logic using custom defined Services and Subscriptions Create an application UI with Mashup Builder Display data from connected devices Test a sample application   Learn More   We recommend the following resources to continue your learning experience:    Capability     Guide Connect Choose a Connectivity Method Build Design Your Data Model Experience Create Your Application UI   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support Getting Started with ThingWorx
View full tip
  Step 4: Data Tables (cont.) Set Properties We now have the Thing with Properties that we want logged, the Service to do said logging, and the Data Table to where the values will be stored   At the top, click Properties and Alerts. Note Data_Table_Test_Thing’s Index_Property and Value_Property.   On the Index_Property line under the Value column, click the "Pencil" icon for Set value of property.   In the slide-out on the right, enter 1.   At the top-right, click the "Check" button for Set. On the Value_Property line under the Value column, click the "Pencil" icon for Set value of property. In the slide-out on the right, enter 10.   At the top-right, click the "Check" button for Set. At the top, click Save.     Store to Data Table At the top, click Services.   On the Add_Data_Table_Entry_Service line under the Execute column, click the "Play" icon for Execute service. A pop-up will open.   At the bottom-right, click Execute. At the bottom-right, click Done. Retrieve from Data Table Return to Test_Data_Table.   At the top, click Services. Scroll down and locate the QueryDataTableEntries built-in Service.   On the QueryDataTableEntries line, click the "Play" icon for Execute service. A pop-up will open. On the bottom-right of the pop-up, click Execute. Note that you should see a single entry, showing the Index_Field at 1 and the the Value_Field at 10   On the bottom-right, click Done. If so desired, you may repeat the previous steps to add additional entries to the Data Table. You will note that the Index and Value fields of the Data Table continue to change in each entry to whatever you have set. Utilizing the functionality of the QueryDataTableEntries built-in Service was just a way to show that the Index and Value items had been correctly logged to the external Data Table. If you wanted to visualize the Data Tables in a grid, it would be as simple as utilizing the Grid Widget and tying Test_Data_Table -> QueryDataTableEntries -> All Data to said Grid. Step 5: Info Tables Just like with Streams and Data Tables, an Info Table requires a Data Shape to format it. In this example, we'll actually use the exact same Data Shape we previously created for the Stream. Create Thing Info Tables are another way to perform non-time-series data storage within the ThingWorx platform. Info Tables used for storage are tied directly to a particular Thing. As such, they are somewhat non-optimal for situations where you’re wanting to aggregate data across multiple Things. Info Tables are a Property Base Type in ThingWorx, in the same manner as a Number, Integer, or String. On the ThingWorx Composer Browse tab, click Modeling > Things, + New.   In the Name field, enter Test_Info_Table_Thing. If Project is not already set, search for and select PTCDefaultProject. In the Thing Template field, search for and select GenericThing.   At the top, click Properties and Alerts. Click + Add. In the Name field, enter Info_Table_Property. Change the Base Type to INFOTABLE. In the Data Shape field, search for and select Test_Data_Shape. This is the same Data Shape we previously created for the Stream. We're just reusing it for formatting the Info Table. Check the Persistent checkbox.   At the top-right, click the "Check" button for Done. At the top, click Save.     Set First Value Now that we have a Thing with an Info Table Property (formatted by our Data Shape), you can set some values for later display in a Mashup. On the new Info_Table_Property line under the Value column, click the "Pencil" button for Set value of property.   On the new pop-up, click the + Add button.   In the Index_Field, enter 1. In the Value_Field, enter 11.   At the bottom-right of the pop-up, click Add. Set Second Value On the pop-up, click the + Add button. In the Index_Field, enter 2. In the Value_Field, enter 22.   At the bottom-right of the pop-up, click Add. Set Third Value On the pop-up, click the + Add button. In the Index_Field, enter 3. In the Value_Field, enter 33.   At the bottom-right of the pop-up, click Add.   At the bottom-right of the pop-up, click Save. At the top, click Save.     Create Mashup Now that we have a Thing with an InfoTable Property and some value-entries in said InfoTable, let's create a Mashup to display those values by using the Grid Widget. On the ThingWorx Composer Browse tab, click VISUALIZATION > Mashups, + New.   On the New Mashup pop-up, leave the defaults, and click OK.   In the Name field, enter Test_Info_Table_Mashup. If Project is not already set, search for and select PTCDefaultProject.  At the top, click Save.   At the top, click Design. With the Widgets tab selected in the top-left, drag-and-drop a Grid Advanced Widget onto the central Canvas area.     Bind Data On the far-right, ensure that the Data tab is selected. Note that you may have to expand this area from the far-right.   Click the + icon. The Add Data pop-up will appear.   In the Entity Filter field, search for and select Test_Info_Table_Thing. In the Services Filter field, enter getprop. Click the right arrow beside the GetPropertyValues Service. On the right under Selected Services, check the Execute on Load checkbox.   At the bottom-right of the pop-up, click Done. Note that Test_Info_Thing -> GetPropertyValues is now available under the Data tab at the far-right. Expand GetPropertyValues > Returned Data > All Data.   Drag-and-drop GetPropertyValues > Returned Data > All Data > Info_Table_Property onto the Grid Advanced Widget in the central Canvas area.   On the Select Binding Target pop-up, select Data.   At the top, click Save. At the top, click View Mashup.   The new Mashup displays all of the Index and Value fields you had previously entered. If you were to add additional entries to the Info Table Property and then refreshed the Mashup, you would see those additional entries as well.   Step 6: Next Steps Congratulations! In this guide, you've learned how to: Differentiate between data storage methods Create a Data Shape to format a Stream, Data Table, and Info Table Create a Value Stream and Stream to store Time-Series Data Create a Data Table and Info Table to store non-Time-Series Data Use built-in methods to log data to a Value Stream or Info Table Create custom Services which log data to a Stream or Data Table Confirm data storage value changes via a built-in Service or Grid Widget Learn More   We recommend the following resources to continue your learning experience:     Capability Guide Build Implement Services, Events, and Subscriptions Additional Resources   If you have questions, issues, or need additional information, refer to:          Resource  Link Community Developer Community Forum Support Data Storage Help Center
View full tip
    Watch a video tutorial on utilizing the Mashup Builder to create a User Interface (UI) for your IoT application.   Guide Concept   This project will introduce the ThingWorx Mashup Builder through the use of an instructional video. Following the steps in this video-guide, you will learn how to use this tool to create a Graphical User Interface (GUI) for your IoT Application. We will teach you how to rapidly create and update a Mashup, which is a custom visualization built to display data from devices according to your application's business and technical requirements.     You'll learn how to   Create new Mashups Choose a Static or Responsive layout Add Widgets to your Mashup Bind data Services to Widgets in your Mashup Create a functional GUI with applied usage of Widgets and Services   NOTE: The estimated time to complete this guide is 30 minutes       Step 1: Video   Click the link below to enjoy the video. You may set the video to full screen by clicking the button in the bottom-right.   If you're following along within your own ThingWorx environment, you may wish to pre-download and extract the attached MBQS_Entities.zip file. It will be used in the later half of the video as a backend data simulator.   Create Your Application UI - Video Guide     Step 2: Next Steps   Congratulations! You've successfully completed the Video Guide - Create Your Application UI, and learned how to:   Create new Mashups Choose a Static or Responsive layout Add Widgets to your Mashup Bind data Services to Widgets in your Mashup Create a functional GUI with applied usage of Widgets and Services   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Data Model Introduction Experience Object-Oriented UI Design Tips   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Mashup Builder Support Help Center
View full tip
    Step 13: C - Support Other Platforms   If you are using a platform that is different than the options provided in the CMake configurations or in the C SDK configurations, you can add your own computer type.   CMake has its own custom toolchain support that enables you to add your computer to the CMake configurations.   Go to the CMake Toolchain. NOTE: The C SDK provides a CMakeList.txt file that contains the setup instructions for the C SDK. Make changes only if you have verified the configurations and compiler information. Create a CMakeList.txt file based on your OS inside the folder in which you would like to setup your application. Modify the Platform Configuration section of the CMakeList.txt file to add your personal computer architecture if it is not already listed. Ensure your configurations are in your application's CMakeList.txt file.   An example of the Platform Configuration section is shown below. if (PLATFORM) if (${PLATFORM} MATCHES "linux-arm") set(OS "linux") set(ARCHITECTURE "arm") set(CMAKE_C_COMPILER ${CMAKE_CURRENT_SOURCE_DIR}/../TOOLS/gcc-linux-arm-cross/bin/arm-angstrom-linux-gnueabi-gcc) set(CMAKE_FIND_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../TOOLS/gcc-linux-arm-cross ${CMAKE_CURRENT_SOURCE_DIR}/../TOOLS/gcc-linux-arm-cross/arm-angstrom-linux-gnueabi) # Set LD_LIBRARY_PATH set(Env{LD_LIBRARY_PATH} "${CMAKE_FIND_ROOT_PATH}/lib/gcc") else () if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(OS "linux") if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") set(ARCHITECTURE "x86_64") set(PLATFORM "linux-x86-64") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_32" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i[36]86") set(ARCHITECTURE "x86_32") set(PLATFORM "linux-x86-32") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "armv5tejl") set(ARCHITECTURE "arm") set(PLATFORM "linux-arm") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "armv[67]l") set(ARCHITECTURE "arm-hwfpu") set(PLATFORM "linux-arm-hwfpu") else () # default to linux-x86_64 set(ARCHITECTURE "x86_64") set(PLATFORM "linux-x86-64") endif() endif ()   An example of how to work with your OS in your application's CMakeList.txt file is shown below: add_executable (SteamSensor src/main.c src/SteamThing.c) target_link_libraries (SteamSensor LINK_PUBLIC twCSdk) if (${OS} MATCHES "windows") add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${CMAKE_BINARY_DIR}/$<CONFIGURATION>/twCSdk.dll" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/twCSdk.dll" COMMENT "Copying C SDK dll to example directory.") if (${TLS_LIB} MATCHES "openssl") # Copy over openssl dll files add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${OPENSSL_SSLEAY_BIN_PATH}" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/ssleay32.dll" COMMENT "Copying ssleay dll to example directory.") add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${OPENSSL_LIBEAY_BIN_PATH}" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/libeay32.dll" COMMENT "Copying ssleay dll to example directory.") endif () endif () if (${OS} MATCHES "linux") if (${TLS_LIB} MATCHES "openssl") # Copy over openssl libraries. add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${OPENSSL_LIB_DIR}/libcrypto.so.1.0.0" "${CMAKE_CURRENT_BINARY_DIR}" COMMAND cmake -E copy_if_different "${OPENSSL_LIB_DIR}/libssl.so.1.0.0" "${CMAKE_CURRENT_BINARY_DIR}" COMMENT "Copying openssl to test directory.") endif () endif () if (${OS} MATCHES "macos") if (${TLS_LIB} MATCHES "openssl") # Copy over openssl libraries. add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${OPENSSL_LIB_DIR}/libcrypto.1.0.0.dylib" "${CMAKE_CURRENT_BINARY_DIR}" COMMAND cmake -E copy_if_different "${OPENSSL_LIB_DIR}/libssl.1.0.0.dylib" "${CMAKE_CURRENT_BINARY_DIR}" COMMENT "Copying openssl to test directory.") endif () endif()     Step 14: Next Steps   Congratulations! You've successfully completed the SDK Reference Guide.   This guide is designed to be used as a reference when developing your application with one of the ThingWorx SDKs.   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Design Your Data Model   Additional Resources   If you have questions, issues, or need additional information, refer to: Resource Link   Community Developer Community Forum   Support C SDK Help Center Java SDK Help Center
View full tip
    Step 10: C - Info Tables   Infotables are used for storing and retrieving data from service calls. An infotable has a DataShapeDefinition that describes the names, base types, and additional information about each field within the table.   In order to create an Infotable, you can do so with the provided macros or functions.   Define With Macros   In order to define Infotables using a macro, use TW_MAKE_INFOTABLE or TW_MAKE_IT. Both macros can be used interchangeably.   NOTE: The macros are all defined in the twMacros.h header file. twInfoTable* it; it = TW_MAKE_IT( TW_MAKE_DATASHAPE(DATSHAPE_NAME_SENSOR_READINGS, TW_DS_ENTRY("ActivationTime", TW_NO_DESCRIPTION ,TW_DATETIME), TW_DS_ENTRY("SensorName", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("Temperature", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("Pressure", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("FaultStatus", TW_NO_DESCRIPTION ,TW_BOOLEAN), TW_DS_ENTRY("InletValve", TW_NO_DESCRIPTION ,TW_BOOLEAN), TW_DS_ENTRY("TemperatureLimit", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("TotalFlow", TW_NO_DESCRIPTION ,TW_INTEGER) ), TW_IT_ROW(TW_MAKE_DATETIME_NOW,TW_MAKE_STRING("Sensor Alpha"),TW_MAKE_NUMBER(60),TW_MAKE_NUMBER(25),TW_MAKE_BOOL(TRUE),TW_MAKE_BOOL(TRUE),TW_MAKE_NUMBER(150),TW_MAKE_NUMBER(77)), TW_IT_ROW(TW_MAKE_DATETIME_NOW,TW_MAKE_STRING("Sensor Beta"),TW_MAKE_EMPTY,TW_MAKE_NUMBER(35),TW_MAKE_BOOL(FALSE),TW_MAKE_BOOL(TRUE),TW_MAKE_EMPTY,TW_MAKE_NUMBER(88)), TW_IT_ROW(TW_MAKE_DATETIME_NOW,TW_MAKE_STRING("Sensor Gamma"),TW_MAKE_EMPTY,TW_MAKE_NUMBER(80),TW_MAKE_BOOL(TRUE),TW_MAKE_BOOL(FALSE),TW_MAKE_NUMBER(150),TW_MAKE_NUMBER(99)) );   Define Without Macros   In order to define Infotables without using a macro, use the twDataShape_CreateFromEntries function.   twInfoTable * it = NULL; twInfoTableRow * row = NULL; it = twInfoTable_Create(ds); if (!it) { TW_LOG(TW_ERROR,"createNewThing: Error creating infotable"); twDataShape_Delete(ds); return TW_ERROR_ALLOCATING_MEMORY; } row = twInfoTableRow_Create(twPrimitive_CreateFromString("SimpleThing_2", TRUE)); if (!row) { TW_LOG(TW_ERROR,"createNewThing: Error creating infotable row"); twInfoTable_Delete(it); return TW_ERROR_ALLOCATING_MEMORY; } twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString("A new Thing", TRUE)); twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString("RemoteThing", TRUE)); twInfoTable_AddRow(it, row);   Retrieve With Macros   Many of the calls to services in ThingWorx will return an InfoTable of information. Below is an example of using the TW_GET_NUMBER_PARAM macro to retrieve values from an Infotable: ///Data is stored in the params variable ///Retrieve the a and b values then store them in variables twInfoTable * params double a, b; TW_GET_NUMBER_PARAM(params, "a", 0, &a); TW_GET_NUMBER_PARAM(params, "b", 0, &b);   Retrieve Without Macros   Below is an example of using the twInfoTable_GetNumber function to retrieve values from an Infotable: ///Data is stored in the params variable ///Retrieve the a and b values then store them in variables twInfoTable * params double a, b; twInfoTable_GetNumber(params, "a", 0, &a); twInfoTable_GetNumber(params, "b", 0, &b);       Step 11: C - Events   Event definitions describe interrupts that ThingWorx can subscribe to in order to receive notifications when something happens.   The parameters for an event definition are:   name description dataShape aspects   In order to create an Event, you can do so with the provided macros or functions.   Define With Macros   In order to define an Event using a macro, you will use TW_DECLARE_EVENT or TW_EVENT. Both macros can be used interchangeably. NOTE: The macros are all defined in the twMacros.h header file. TW_EVENT("SteamSensorFault", "Steam sensor event", TW_MAKE_DATASHAPE( "SteamSensorFault", TW_DS_ENTRY("message",TW_NO_DESCRIPTION,TW_STRING) ) );   Define Without Macros   In order to define an Event without using a macro, you will use the twApi_RegisterEvent function. See an example below of how to utilize the twApi_RegisterEvent function and adding a row of data: twApi_RegisterEvent(TW_THING, "SteamSensor", "SteamSensorFault", "Steam sensor event", ds);   Fire With Macros   In order to fire an Event using a macro, you will use TW_FIRE_EVENT.   NOTE: The macros are all defined in the twMacros.h header file. TW_FIRE_EVENT(thingName, "SteamSensorFault", TW_MAKE_IT(TW_MAKE_DATASHAPE( "SteamSensorFault", TW_DS_ENTRY("message", TW_NO_DESCRIPTION, TW_STRING) ), TW_IT_ROW(TW_MAKE_STRING(msg)) ));   Fire Without Macros   In order to fire an Event without using a macro, you will use the twApi_FireEvent function. See an example below of how to utilize the twApi_FireEvent function and adding a row of data: twApi_FireEvent(TW_THING, "SteamSensor", "SteamSensorFault", eventInfoTable, -1, TRUE)       Step 12: C - Services   Service Handler Callbacks The service callback function is registered to be called when a request for a specific service is received from the ThingWorx Platform. These functions must have the same signature as shown here: typedef enum msgCodeEnum (*service_cb) (const char * entityName, const char * serviceName, twInfoTable * params,twInfoTable ** content, void * userdata) Below is an example of a single service that adds two numbers that can be registered with and without macros: /***************** Service Callbacks ******************/ /* Example of handling a single service in a callback */ enum msgCodeEnum addNumbersService(const char * entityName, const char * serviceName, twInfoTable * params, twInfoTable ** content, void * userdata) { double a, b, res; TW_LOG(TW_TRACE,"addNumbersService - Function called"); if (!params || !content) { TW_LOG(TW_ERROR,"addNumbersService - NULL params or content pointer"); return BAD_REQUEST; } twInfoTable_GetNumber(params, "a", 0, &a); twInfoTable_GetNumber(params, "b", 0, &b); res = a + b; *content = twInfoTable_CreateFromNumber("result", res); if (*content) return SUCCESS; else return INTERNAL_SERVER_ERROR; }   NOTE: The return value of the function is TWX_SUCCESS if the request completes successfully or an appropriate error code if not (should be a message code enumeration as defined in twDefinitions.h).   Register Service Callback   In order to register a service handler callback using macros, utilize TW_DECLARE_SERVICE as shown below: TW_MAKE_THING(thingName,TW_THING_TEMPLATE_GENERIC); TW_DECLARE_SERVICE( "AddNumbers", "Add two numbers together", TW_MAKE_DATASHAPE(NO_SHAPE_NAME, TW_DS_ENTRY("a", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("b", TW_NO_DESCRIPTION ,TW_NUMBER)), TW_NUMBER, TW_NO_RETURN_DATASHAPE, addNumbersService );     Click here to view Part 9 of this guide
View full tip
  Step 8: C - Properties (cont.)   Register Properties   Registering properties and services with the API:   Tells the API what callback function to invoke when a request for that property or service comes in from ThingWorx. Gives the API information about the property or service so that when ThingWorx browses the Edge device, it can be informed about the availability and the definition of that property or service. If you used the TW_PROPERTY macro, your property has been registered. If using function calls, to register a property, use the twApi_RegisterProperty. The documentation for this function can be found in [C SDK HOME DIR]/src/api/twApi.h.   NOTE: If you used the provided Macros to create your property, it has already been registered. Bind the Thing in order for your property to be bound.   An example of registering a property is as follows:   twApi_RegisterProperty(TW_THING, “SimpleThing_1”, "FaultStatus", TW_BOOLEAN, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, “SimpleThing_1”, "InletValve", TW_BOOLEAN, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, “SimpleThing_1”, "Pressure", TW_NUMBER, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, “SimpleThing_1”, "Temperature", TW_NUMBER, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, thingName, "BigGiantString", TW_STRING, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, thingName, "Location", TW_LOCATION, NULL, "ALWAYS", 0, propertyHandler, NULL);   Update Properties   Property values can be updated using the provided Macros or using the API directly.   NOTE: Update a property does not send it to the server. To Push a property after updates have been made, use the TW_PUSH_PROPERTIES_FOR function that can be found in the [C SDK HOME DIR]/src/api/twMacro.h header file.   With Macros   The TW_SET_PROPERTY macro updates a property in ThingWorx and can be found in the [C SDK HOME DIR]/src/api/twMacro.h header file. The usage can be seen in the example below: TW_SET_PROPERTY(thingName, "FlowCount", TW_MAKE_NUMBER(5)); TW_SET_PROPERTY(thingName, "TotalFlow", TW_MAKE_NUMBER(rand() / (RAND_MAX / 10.0))); TW_SET_PROPERTY(thingName, "Pressure", TW_MAKE_NUMBER(18 + rand() / (RAND_MAX / 5.0))); TW_SET_PROPERTY(thingName, "Location", TW_MAKE_LOC(gpsroute[location_step].latitude,gpsroute[location_step].longitude,gpsroute[location_step].elevation));   Without Macros   The twInfoTable_CreateFrom and twApi_SetSubscribedProperty functions updates a property in ThingWorx and can be found in the [C SDK HOME DIR]/src/api/twApi.h header file. The usage can be seen in the example below: if (strcmp(propertyName, "count") == 0) { twInfoTable_GetInteger(*value, propertyName, 0, &properties.count); twApi_SetSubscribedProperty(entityName, propertyName, twPrimitive_CreateFromNumber(properties.count), FALSE, TRUE); } if (strcmp(propertyName, "InletValve") == 0) twInfoTable_GetBoolean(*value, propertyName, 0, &properties.InletValve);   Retrieve Properties   Property values can be retrieved using the provided Macros or using the API directly.   With Macros   The TW_GET_PROPERTY macro retrieves a property in ThingWorx and can be found in the [C SDK HOME DIR]/src/api/twMacro.h header file. The usage can be seen in the example below: double temp = TW_GET_PROPERTY(thingName, "Temperature").number;   NOTE: You can use the macro TW_GET_PROPERTY_TYPE to get the property type. The signature and function information can be found in the [C SDK HOME DIR]/src/api/twMacro.h header file.   Without Macros   The twInfoTable_Get functions updates a property in ThingWorx and can be found in the [C SDK HOME DIR]/src/api/twApi.h header file. The usage can be seen in the example below:   twInfoTable **inletValue = NULL; twInfoTable **temp = NULL; twInfoTable **location = NULL; *inletValue = twInfoTable_CreateFromBoolean(propertyName, properties.InletValve); *temp = twInfoTable_CreateFromNumber(propertyName, properties.Temperature); *location = twInfoTable_CreateFromLocation(propertyName, &properties.Location);   Property Change Listeners   Using the Observer pattern, you are able to take advantage of the property change listener functionality. With this pattern, you are able to create functions that will be notified when a value of a property has been changed (whether on the server or locally by your program when the TW_SET_PROPERTY macro is called).   Add a Property Change Listener   In order to add a property change listener, you will call the twExt_AddPropertyChangeListener function using the name of the Thing (entityName), the property this listener should watch, and the function that will be called when the property has changed. The usage can be seen in the example below: void simplePropertyObserver(const char * entityName, const char * thingName,twPrimitive* newValue){ printf("My Value has changed\n"); } void test_simplePropertyChangeListener() { { TW_MAKE_THING("observedThing",TW_THING_TEMPLATE_GENERIC); TW_PROPERTY("TotalFlow", TW_NO_DESCRIPTION, TW_NUMBER); } twExt_AddPropertyChangeListener("observedThing",TW_OBSERVE_ALL_PROPERTIES,simplePropertyObserver); TW_SET_PROPERTY("observedThing","TotalFlow",TW_MAKE_NUMBER(50)); }   NOTE: Setting the propertyName parameter to NULL or TW_OBSERVE_ALL_PROPERTIES, the function specified by the propertyChangeListenerFunction parameter will be used for ALL properties.   Remove a Property Change Listener   When releasing the memory for your application or done with utilizing listeners for the property, call the twExt_RemovePropertyChangeListener function. This usage can be seen in the example below:   void simplePropertyObserver(const char * entityName, const char * thingName,twPrimitive* newValue){ printf("My Value has changed\n"); } twExt_RemovePropertyChangeListener(simplePropertyObserver);     Step 9: C - Data Shapes   DataShapes are used for Events, Services, and InfoTables. In order to create a DataShape, you can do so with the provided macros or functions.   Define With Macros   In order to define a DataShape using a macro, use TW_MAKE_DATASHAPE.   NOTE: The macros are all defined in the twMacros.h header file. TW_MAKE_DATASHAPE("SteamSensorReadingShape", TW_DS_ENTRY("ActivationTime", TW_NO_DESCRIPTION ,TW_DATETIME), TW_DS_ENTRY("SensorName", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("Temperature", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("Pressure", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("FaultStatus", TW_NO_DESCRIPTION ,TW_BOOLEAN), TW_DS_ENTRY("InletValve", TW_NO_DESCRIPTION ,TW_BOOLEAN), TW_DS_ENTRY("TemperatureLimit", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("TotalFlow", TW_NO_DESCRIPTION ,TW_INTEGER) );   Define Without Macros   In order to define a DataShape without using a macro, use the twDataShape_CreateFromEntries function.   twDataShape * ds = 0; ds = twDataShape_Create(twDataShapeEntry_Create("ID", NULL, TW_INTEGER)); twDataShape_SetName(ds, "StringMap"); twDataShape_AddEntry(ds, twDataShapeEntry_Create("Value", NULL, TW_STRING));     Click here to view Part 8 of this guide
View full tip
  Step 8: C - Properties   In the ThingWorx environment, a Property represents a data point, which has a:   Name Value Timestamp Quality (optional)   Define Properties   You can define attributes, base types and other aspects of ThingWorx properties.   Attributes   The table below provides information on the different attributes that are used to define a property.   Attribute Details name Specifies the name of the property that will appear in ThingWorx when users browse to bind the related Thing. description Provides additional information for the property. baseType Specifies the type of the property. For a list of base types supported by the SDK, refer to the BaseTypes chart below.   BaseTypes   The table below provides information on the different types of properties that can be created in ThingWorx.   BaseType  Description TW_NOTHING An empty value. TW_STRING A modified UTF8 encoded string. Data and length are stored in val.bytes and val.len, respectively. The twPrimitive owns the data pointer and will free it when deleted. TW_STRING types are null terminated. TW_NUMBER A C double value, stored in val.double. TW_BOOLEAN Represented as a single char, stored in val.boolean. TW_DATETIME A DATETIME value, which is an unsigned 64 bit value representing milliseconds since the epoch 1/1/1970. Data is stored in val.datetime. TW_INFOTABLE A pointer to a complex structure (defined in the next section) and stored in val.infotable. The twPrimitive owns this pointer and will free up the memory pointed to when the twPrimitive is deleted. TW_LOCATION A structure consisting of three double floating point values – longitude, latitude, and elevation. Stored as val.location. TW_BLOB A pointer to a character array. Data and length are stored in val.bytes and val.len, respectively. Differs from TW_STRING in that the array may contain nulls. The twPrimitive owns the data pointer and will free it when deleted. TW_IMAGE Identical to TW_BLOB except for the type difference. TW_INTEGER Assigned 4 by integral value. Stored as val.integer. TW_VARIANT Pointer to a structure that contain a type enum and a twPrimitive value. The pointer is stored as val.variant. The twPrimitive owns the pointer and will free the structure when deleted.   The following base types are all of the TW_STRING family and are stored similarly:   TW_XML,TW_JSON TW_QUERY TW_HYPERLINK TW_IMAGELINK TW_PASSWORD TW_HTML TW_TEXT TW_TAGS TW_GUID TW_THINGNAME TW_THINGSHAPENAME TW_THINGTEMPLATENAME TW_DATASHAPENAME TW_MASHUPNAME TW_MENUNAME TW_BASETYPENAME TW_USERNAME TW_GROUPNAME TW_CATEGORYNAME TW_STATEDEFINITIONNAME TW_STYLEDEFINITIONNAME TW_MODELTAGVOCABULARYNAME TW_DATATAGVOCABULARYNAME TW_NETWORKNAME TW_MEDIAENTITYNAME TW_APPLICATIONKEYNAME TW_LOCALIZATIONTABLENAME TW_ORGANIZATIONNAME   Aspects   Aspects define the ways to interact with a property. The table below provides information on details that make up the Aspects attribute of a property.   Attribute Macro Description isPersistent TW_ASPECT_ISPERSISTENT Set to TRUE for the ThingWorx server to persist the value even if it restarts. It is extremely expensive to have persistent values, so it is recommended to set this value to FALSE unless absolutely necessary. isReadOnly TW_ASPECT_ISREADONLY Set to TRUE to inform the ThingWorx server that this value is only readable and cannot be changed by a request from the server. dataChangeType TW_ASPECT_DATACHANGETYPE Describes how the ThingWorx server responds when the value changes in the client application. Subscriptions to these value changes can be modeled in ThingWorx Platform. If nothing needs to react to the property change, set this value to NEVER. dataChangeThreshold TW_ASPECT_DATACHANGETHRESHOLD Defines how much the value must change to trigger a change event. For example 0 (zero) indicates that any change triggers an event. A value of 10 (ten) for example would not trigger an update unless the value changed by an amount greater than or equal to 10. defaultValue TW_ASPECT_DEFAULT_VALUE The default value is the value that ThingWorx Platform uses when the RemoteThing connected to the device first starts up and has not received an update from the device. The value is different based on the different value for each base type. cacheTime N/A The amount of time that ThingWorx Platform caches the value before reading it again. A value of -1 informs the server that the client application always sends its value and the server should never go and get it. A value of 0 (zero) indicates that every time the server uses the value, it should go and get it from the client application. Any other positive value indicates that the server caches the value for that many seconds and then retrieves it from the client application only after that time expired. pushType TW_ASPECT_PUSHTYPE Informs ThingWorx Platform how the client application pushes its values to the server.   NOTE: cacheTime and dataChangeThreshold are for subscribed (bound) properties ONLY.   DataChangeType Values   This field acts as the default value for the data change type field of the property when it is added to the remote Thing. The possible dataChangeType values are below:   Value Description ALWAYS Always notify of the value change even if the new value is the same as the last reported value. VALUE Only notify of a change when a newly reported value is different than its previous value. ON For BOOLEAN types, notify only when the value is true. OFF For BOOLEAN types only, notify when the value is false. NEVER Ignore all changes to this value.   PushType Values   This aspect works in conjunction with cacheTime. The possible pushType values are below:   Value Description ALWAYS Send updates even if the value has not changed. It is common to use a cacheTime setting of -1 in this case. VALUE Send updates only when the value changes. It is common to use a cacheTime setting of -1 in this case. NEVER Never send the value, which indicates that ThingWorx server only writes to this value.It is common to use a cacheTime setting of 0 or greater in this case. DEADBAND Added to support KEPServer, this push type is an absolute deadband (no percentages). It provides a cumulative threshold, such that the Edge device should send an update if its current data point exceeds Threshold compared to the last value sent to ThingWorx Platform. It follows existing threshold fields limits.   With Macros   The C SDK provides a list of macros to help make development easier and faster.   The macros TW_PROPERTY and TW_PROPERTY_LONG define a property of a Thing. This macro must be preceeded by either TW_DECLARE_SHAPE,TW_DECLARE_TEMPLATE or TW_MAKE_THING macros because these macros declare variables used by the property that follow them. The functions return TW_OK on success, {TW_NULL_OR_INVALID_API_SINGLETON,TW_ERROR_ALLOCATING_MEMORY,TW_INVALID_PARAM,TW_ERROR_ITEM_EXISTS} on failure.   NOTE: The macros are defined in the file, twMacros.h.   This example shows how to utilize these functions:   TW_MAKE_THING(thingName,TW_THING_TEMPLATE_GENERIC); TW_PROPERTY("Pressure", TW_NO_DESCRIPTION, TW_NUMBER); TW_ADD_BOOLEAN_ASPECT("Pressure", TW_ASPECT_ISREADONLY,TRUE); TW_ADD_BOOLEAN_ASPECT("Pressure", TW_ASPECT_ISLOGGED,TRUE); TW_PROPERTY("Temperature", TW_NO_DESCRIPTION, TW_NUMBER); TW_ADD_BOOLEAN_ASPECT("Temperature", TW_ASPECT_ISREADONLY,TRUE); TW_ADD_BOOLEAN_ASPECT("Pressure", TW_ASPECT_ISLOGGED,TRUE); TW_PROPERTY("TemperatureLimit", TW_NO_DESCRIPTION, TW_NUMBER); TW_ADD_NUMBER_ASPECT("TemperatureLimit", TW_ASPECT_DEFAULT_VALUE,320.0); TW_PROPERTY("Location", TW_NO_DESCRIPTION, TW_LOCATION); TW_ADD_BOOLEAN_ASPECT("Location", TW_ASPECT_ISREADONLY,TRUE); TW_PROPERTY("Logfile", TW_NO_DESCRIPTION, TW_STRING); TW_ADD_BOOLEAN_ASPECT("Logfile", TW_ASPECT_ISREADONLY,TRUE);   NOTE: TW_PROPERTY_LONG performs the same actions as TW_PROPERTY, except that it offers more options. When using TW_PROPERTY to declare a property you are accepting the use of the default property handler. This property handler will allocate and manage the storage used for this property automatically.   Without Macros   Property values can be set with defaults using the aspects setting. Setting a default value in the client will affect the property in the ThingWorx platform after binding. It will not set a local value in the client application. Two types of structures are used by the C SDK to define properties.   Structure Notes Code Property Definitions Describes the basic information for the properties that are going to be available to ThingWorx and can be added to a client application. twPropertyDef *property1 = twPropertyDef_Create(property, TW_BOOLEAN, "Description for Property1", "NEVER", 0); cJSON_AddStringToObject(tmp->aspects,"isReadOnly", "FALSE"); cJSON_AddStringToObject(tmp->aspects,"isPersistent", "FALSE"); cJSON_AddStringToObject(tmp->aspects,"isPersistent", "FALSE"); Property Values Associates the property name with a value, timestamp, and quality. twPrimitive * value = twPrimitive_CreateFromNumber(properties.TempProp); twProperty * tempProp = twProperty_Create("TempProperty", value, NULL);       Click here to view Part 7 of this guide
View full tip
    Step 3: Streams (cont.) Store to Stream Now that the Stream, the Thing (and its Properties), and the Thing's Service are all in place, we can execute the Service (along with some Property changes) to demonstrate that the values are getting archived externally to the Stream. At the top, click Properties and Alerts. Note the previously-created Index_Property and Value_Property.   For Index_Property's Value column, click the "pencil" icon for Set value of property.   In the slide-out on the right, enter 1.   At the top-right, click the "Check" button for Set. For Value Property, click the "Pencil" icon for Set value of property.   In the slide-out on the right, enter 10.   At the top-right, click the "Check" button for Set. At the top, click Save.   With the Thing's Properties set to new values, you can now call your custom Service to store those values to the external Stream (along with an auto-generated timestamp). At the top, click Services.   On the Add_Stream_Entry_Service line, click the "Play" button for Execute Service.   At the bottom-right of the pop-up, click the Execute button.   At the bottom-right, click the Done button.   Retrieve from Stream To confirm that our Thing's custom Service is correctly logging our Property values, we'll now use a built-in Service of the Stream to retrieve the stored values. This same QueryStreamEntriesWithData Service could alternately be used to populate various Mashup Widgets to view the data in a more convenient format. Return to the Test_Stream Entity.   On the top, click Services.   Scroll down and locate the QueryStreamEntriesWithData Service's Execute service button.   At the bottom-right of the pop-up, click Execute. Note that you should see a single entry, showing the Index_Field at 1, the Value_Field at 10, and a timestamp of when the information was pushed to the Stream.   At the bottom-right, click Done. To further confirm external storage to the Stream, you may repeat the previous steps to confirm additional Property Value Storage with timestamping. Furthermore, you could create a Mashup utilizing either the Time-Series Chart or a Grid to display the data stored within the Stream. Step 4: Data Tables Just like with Streams, you also need a Data Shape to format a Data Table. In this example, we'll actually use the exact same Data Shape we previously created for the Stream. Create Data Table Both Data Tables and Info Tables may be appropriate for your non-time-series mass data storage needs. However, a Data Table is not tied to a Thing as an Info Table Property would be. If your non-time-series information is coming from multiple different sources, then it would generally be appropriate to use a Data Table. On the ThingWorx Composer Browse tab, click Data Storage > Data Tables, + New. On the Choose Template pop-up, select DataTable, and click OK. In the Name field, enter Test_Data_Table If Project is not already set, search for and select PTCDefaultProject. In the Data Shape field, search for and select Test_Data_Shape. This is the same Data Shape we previously created for the Stream. We're just reusing it for formatting the Data Table.  At the top, click Save. Create Thing Now that we have a Data Table, let's create a Thing with some Properties that we'll eventually log to the external Data Table. On the ThingWorx Composer Browse tab, click MODELING -> Things, + New. In the Name field, enter Data_Table_Test_Thing. If Project is not already set, search for and select PTCDefaultProject. In the Thing Template field, search for and select GenericThing. At the top, click Properties and Alerts. Click + Add. In the Name field, enter Index_Property. Change the Base Type to Integer. Check the Persistent checkbox. At the top, click the "Check with a +" button for Done and Add. In the Name field, enter Value_Property. Change the Base Type to Number. Check the Persistent checkbox. At the top-right, click the "Check" button for Done. Create Service We now have both a Data Table and a Thing with Properties that we want logged. Now we need to create a Service which does the logging. At the top, click Services. Click + Add. In the Name field, enter Add_Data_Table_Entry_Service. Under New Service on the left, click the Snippets tab. In the Filter field, type data table. Expand the Stream, Blog, Data Table section. A pop-up will open. Beside Add/Update Data Table, click the right arrow. In the Search Data Tables field, type test. Select Test_Data_Table. Note that a section of Javascript code has now been added to the Script window. Click the green Insert Code Snippet button. Modify Snippet On the 6th line of code, double-click undefined to select it. On the left, expand the Me/Entities tab. Under the Me/Entities tab, expand Properties. Note that this is not the Properties and Alerts at the top of Composer Click the right arrow beside Value_Property. Note that undefined has been replaced by me.Value_Property. On the 7th line of code, double-click the remaining undefined to select it. Click the right arrow beside Index_Property. Note that the second undefined has been replaced by me.Index_Property.   Click Done to stop editing the custom Service.   At the top, click Save.     Click here to view Part 4 of this guide.
View full tip
    Step 7: C - Entities and Functions   All SDKs require a RemoteThing be created in ThingWorx in order to communicate. If many Things are to be created with the same properties, services, and events, we recommend that a Thing Template be derived from one of the supplied RemoteThing templates.   NOTE: The macros are all defined in the twMacros.h header file.   Define ThingShape   ThingShapes are used in the ThingWorx object-oriented Data Model and used to create Things later on. In order to create a ThingShape, you can do so with the provided macros. In order to define a ThingShapes using a macro, you will use TW_DECLARE_SHAPE or TW_SHAPE. TW_DECLARE_SHAPE("SteamLocation","Address Shape","UniqueNameSpace");   Define ThingTemplate   ThingTemplates are used in the ThingWorx object oriented Data Model and used to create Things later on. In order to create a ThingTemplate, you can do so with the provided macros. In order to define a ThingTemplate using a macro, you will use TW_DECLARE_TEMPLATE or TW_TEMPLATE. TW_DECLARE_TEMPLATE("SteamLocationTemplate",TW_THING_TEMPLATE_GENERIC,"UniqueNameSpace");   Define Thing   Things are used in the Data Model and a staple in IoT development. In order to create a Thing, you can do so with the provided macros or functions.   Function Example In order to define a Thing with a macro, you will use TW_MAKE_THING. TW_MAKE_THING("SteamSensor", TW_THING_TEMPLATE_GENERIC); In order to define a Thing without using a macro, you will use the twExt_CreateThingFromTemplate function. twExt_CreateThingFromTemplate("SteamSensor","WarehouseTemplate", "SimpleShape", "AddressShape","InventoryShape",NULL);   Register Functions   ThingWorx provides functionality for a Thing to be bound or connected to the server. Function Notes twExt_RegisterPolledTemplateFunction Register a function to be called periodically after this Thing has been created twApi_RegisterSynchronizeStateEventCallback Called after binding to notify your application about what fields are bound on the server. Will also be called each time bindings on a Thing are edited. twApi_RegisterBindEventCallback Runs whenever a Thing is bound or unbound.   Bind & Subscribe   You will use the TW_BIND macro or the twApi_BindThing function with the Thing name provided as a parameter. The documentation can be found in [C SDK HOME DIR]/src/api/twMacro.h and [C SDK HOME DIR]/src/api/twApi.h respectfully.   NOTE: Registered properties are bound or subscribed after they have been registered.   Bind Callbacks   You may want to track exactly when your edge entities are successfully bound to or unbound from ThingWorx Core. The reason for this is that only bound items should be interacting with ThingWorx Core and it will never forward a request to a corresponding remote thing in its database when the request is targeted at an entity that is not bound. Call the twApi_RegisterBindEventCallback() function to register your bind callback function as seen below with a function we later define called BindEventHandler:   To learn about a specific bound Thing (ie, SteamSensor): twApi_RegisterBindEventCallback("SteamSensor", BindEventHandler, NULL);   To learn about all bound Things, leave the first parameter null: twApi_RegisterBindEventCallback(NULL, BindEventHandler, NULL An example of the function is below: void BindEventHandler(char *entityName, char isBound, void *userdata) { if (isBound) TW_LOG(TW_FORCE,"bindEventHandler: Entity %s was Bound", entityName); else TW_LOG(TW_FORCE,"bindEventHandler: Entity %s was Unbound", entityName); }   Create Tasks   The SDK contains a tasker framework that you can use to call functions repeatedly at a set interval. You can use the tasker to drive both the connectivity layer of your application and the functionality of your application. However, using the tasker is optional.   NOTE: The built-in tasker is a simple round-robin execution engine that will call all registered functions at a rate defined when those functions are registered. If using a multitasking or multi-threaded environment you may want to disable the tasker and use the native environment. If you choose to disable the tasker, you must call twApi_TaskerFunction() and twMessageHandler_msgHandlerTask() on a regular basis (every 5 milliseconds or so). Un-define this setting if you are using your own threads to drive the API, as you do not want the tasker running in parallel with another thread running the API.   To properly initialize the tasker, you must define ENABLE_TASKER: #define ENABLE_TASKER 1 An example of a data collection task is seen below: /*************** Data Collection Task ****************/ /* This function gets called at the rate defined in the task creation. The SDK has a simple cooperative multitasker, so the function cannot infinitely loop. Use of a task like this is optional and not required in a multithreaded environment where this functionality could be provided in a separate thread. */ #define DATA_COLLECTION_RATE_MSEC 2000 void dataCollectionTask(DATETIME now, void * params) { /* TW_LOG(TW_TRACE,"dataCollectionTask: Executing"); */ properties.TotalFlow = rand()/(RAND_MAX/10.0); properties.Pressure = 18 + rand()/(RAND_MAX/5.0); properties.Location.latitude = properties.Location.latitude + ((double)(rand() - RAND_MAX))/RAND_MAX/5; properties.Location.longitude = properties.Location.longitude + ((double)(rand() - RAND_MAX))/RAND_MAX/5; properties.Temperature = 400 + rand()/(RAND_MAX/40); /* Check for a fault. Only do something if we haven't already */ if (properties.Temperature > properties.TemperatureLimit && properties.FaultStatus == FALSE) { twInfoTable * faultData = 0; char msg[140]; properties.FaultStatus = TRUE; properties.InletValve = TRUE; sprintf(msg,"%s Temperature %2f exceeds threshold of %2f", thingName, properties.Temperature, properties.TemperatureLimit); faultData = twInfoTable_CreateFromString("msg", msg, TRUE); twApi_FireEvent(TW_THING, thingName, "SteamSensorFault", faultData, -1, TRUE); twInfoTable_Delete(faultData); } /* Update the properties on the server */ sendPropertyUpdate(); }   NOTE: The Windows-based operating systems have a tick resolution (15ms) that is higher than the tick resolutions requested by the C SDK (5ms).       Click here to view Part 6 of this guide  
View full tip
    Step 7: Add Grid   It might also be helpful to display the data you've used to build the ThingWorx Analytics model.   In the future, this might be split out into an entirely separate page/Mashup that is exclusively devoted to backend model creation, but that would be beyond the scope of this guide.   For now, we'll simply display that collected data via the Grid Widget      1. On the EEFV_Mashup, drag-and-drop a Grid Advanced Widget onto the bottom-left Canvas section..     2. On the top-right Data tab, click the green </> button beside Things_EdgeThing. Note that this will open the Add Data pop-up, but with EdgeThing pre-selected.   3. In the Services Filter field, type getproperties.   4. Click the right-arrow beside GetProperties to add it to Selected Services on the right.   5. Check Execute on Load.     6. Click Done.   7. Under the Data tab, expand GetProperties to reveal the options.     8. Drag-and-drop Things_EdgeThing > GetProperties > infoTableProperty onto the Grid Advanced Widget.     9. On the Select Binding Target pop-up, click Data.     10. Click Save.   11. Click View Mashup.         Step 8: Add Controls   Throughout this Learning Path, it has been recommended that you stop Analysis Events when not actively using their functionality.   However, this requires going into the backend of ThingWorx Analytics to disable the event, which is not ideal.   Instead, let's enable or disable the Analysis Event from inside the Mashup by adding some Button Widgets to directly interface the Analytics backend for us.       1. Click the bottom-right Canvas section to select it.         2. In Mashup Builder top-left, click the Layout tab.         3. Under Positioning, click the Static radio-button.         4. Click the Widgets tab.       5. Drag-and-drop a Button Widget onto the bottom-right section.         6. Drag-and-drop another Button Widget onto the bottom-right section.       7. Drag-and-drop a Text Field Widget onto the bottom-right section.       8. Click Save.       Bring in More Data   Now that we have Buttons to trigger enable/disable, as well as a Text Field to display information, we now need to bring in some additional Mashup Data Services to interact with the ThingWorx Analytics backend.       1. Click the green + button at the top of the Data tab.       2. In the Entity Filter field, search for and  select TW.AnalysisServices.EventManagementServicesAPI.       3. In the Services Filter field, search for and add QueryAnalysisEvents by clicking the right arrow.       4. Check Execute on Load.         5. In Services Filter, search for and select EnableAnalysisEvent by clicking the right arrow. Note that you should NOT check "Execute on Load", as we'll trigger this Service only when the Button is clicked.     6. In Services Filter, search for and select DisableAnalysisEvent by clicking the right arrow. Likewise, do NOT check "Execute on Load" here either.       7. Click Done.         8. Click Save.     Display Event Key   To enable or disable Analytics Events, we need to know the eventId, which is returned by QueryAnalysisEvent Service as the parameter labeled key.   We'll bind that to the Text Field Widget for later usage in enabling/disabling.        1. Change the top-button's Label Property to Enable Analytics Event.       2. Change the bottom-button's Label Property to Disable Analytics Event.         3. Under the Data tab, expand QueryAnalysisEvents > Returned Data > All Data to reveal the options. .       4. Drag-and-drop QueryAnalysisEvents > Returned Data > All Data > key to the TextField Widget.         5. On the Select Binding Target pop-up, click Text.         6. Click Save.     Enable/Disable Analytics Events   Now that we know the key/eventId, we can call the EnableAnalysisEvent and DisableAnalysisEvent services.       1. Under the Data tab, expand EnableAnalysisEvent > Parameters to reveal eventId.       2. Click the Text Field Widget to select it, and then click the top-left drop down to reveal the options.         3. Drag-and-drop the Text Field's Text Property onto EnableAnalysisEvent > Parameters > eventId.         4. Repeat steps 1-3 for DisableAnalysisEvent.         5. Click the Enable Analytics Event Button Widget to select it, then click the top-left to reveal the drop down option .       6. Drag-and-drop the Clicked Event onto the EnableAnalysisEvent Service under the Data tab.         7. Repeat steps 5-6 for DisableAnalysisEvent, using the other Button Widget.         8. Click Save     Step 9: View Mashup   Throughout this guide, we've added various additional functionality to our MVP Mashup. At this point, you could continue to update the Mashup as you see fit.   For instance, you could change the background color of the top-left section to better match the header. Or you could further modify the original Mashup shown in the Contained Mashup Widget so that it better fits in the allowed space. You could add another Label Widget to the Header section to also display the company's motto / tag-line.   Regardless, when you are done with modifications, Save and click View Mashup.     Note that you can left-click-and-drag on the Time Series Chart to select particular time ranges. Or you could add a Time Selector Widget to the bottom-right section to control it there.   Similarly, you could add controls for the Grid Widget to only show the Identifier ranges in which you were interested.   Or you could split out the Model-creation values to a completely separate Mashup as previously discussed.   The extent to which you develop your Mashup is entirely up to you.        Step 10: Next Steps   Congratulations. You've completed the Enhanced Engine Failure Visualization guide. In this guide, you learned how to:   Create a Mashup with a Header Divide your Mashup into Sub-sections Use a Contained Mashup to reuse development Store historical data in a Value Steam Display historical data in a Line Chart Show spreadsheet data via a Grid Advanced Widget Tie Mashup controls into the ThingWorx backend   This is the last guide in the Vehicle Predictive Pre-Failure Detection with ThingWorx Platform learning path.   Learn More   We recommend the following resources to continue your learning experience:   Capability  Guide Build Implement Services, Events, and Subscriptions Guide   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Analytics Manager Help Center
View full tip
  Step 5: Contained Mashup   Our Minimum Viable Product (MVP) Mashup which we created in the last guide did have valid information.   Being able to display the inputs coming from the engine, as well as the analytical results coming from ThingWorx Analytics, are certainly items we don’t want to lose in this new, more complete Mashup.   Rather than recreating that work from scratch, we’ll simply include that previous Mashup in one of our sub-section via the Contained Mashup Widget.       1. Click on the top-left section to select it, and ensure that you’re on the Widgets tab in the top-left.       2. Drag-and-drop a Contained Mashup Widget onto the top-left section.       3. With the Contained Mashup Widget selected, return to the Properties tab in the bottom-left.       4. Scroll down and locate the Name Property.       5. Search for and select EFPG_Mashup       6. Click Save.     Add Column Labels   The original Mashup we created (and have now embedded in the new one) had some labels for the inputs and outputs. However, you had to know what things like “s1_fb1” meant to understand that that was an input.   We can go back to the original EPFG_Mashup, make some modifications for greater clarity, and those changes will also carry over to our new Mashup.       1. Reopen the old EPFG_Mashup on the Design tab.       2. Move all of the Widgets down to leave some extra room at the top.       3. Drag-and-drop two Divider Widgets onto the Canvas above both the Inputs and Results columns.       4. Select a Divider Widget, and go to its Style Properties.       5. Expand Base > Line to reveal the background Style Property.       6. Click on the default gray color to see the available options.       7. Choose the built-in black at the bottom, and click Select.       8. Make the same modification to the other Divider Widget.       9. Drag-and-drop two more Label Widgets onto the Canvas above the two columns.       10. Change their LabelText Properties to Inputs and Results, respectively.     Change Background and Size       1. From the Explorer tab in the top-left, select the container.       2. Select the Style Properties tab in the bottom-left and expand Base > Container.       3. Change the background Style Property to a color you prefer.       4. With the container still selected in the Explorer tab, drag the corners of the Mashup to reduce its size.       5. You could even move the Results column over, place the Auto Refresh Widget underneath, and then reduce the container size even further.       6. Click Save.     View Mashup Thus Far   With the changes to the previous EFPG_Mashup now complete, let’s ensure that everything carried over to our new Mashup.       1. Return to EEFV_Mashup.       2. Click Save.       3. Click View Mashup.   Note how the various changes we made to the base Mashup are also being shown, via a Contained Mashup Widget, in our new Mashup.   Splitting out functionality to a separate Mashup that is then embedded where needed is a great way to re-use content and simplify development.       Step 6: Add Chart   Our original Mashup (which has now been embedded in our new one) shows the instantaneous analytical results based on the inputs coming from the Edge MicroServer (EMS).   However, when investigating remote customer issues, it might be helpful to see some historical trends. A temporary "blip" of a low-grease indication might be worrisome, but it may not require immediate intervention unless the issue was occuring consistently or for extended periods of time.   Fortunately, creating a historical record is relatively simple in ThingWorx Foundation.   All that is really needed is a place in which to store the past records.   One of the easiest such storage methods is a Value Stream.       1. In ThingWorx Foundation, click Browse > Data Storage > Value Streams.       2. Click + New.       3. On the Choose Template pop-up, select ValueStream and click OK.       4. In the Name field, type EEFV_ValueStream.       5. If Project is not already set, search for and select PTCDefaultProject.       6. At the top, click Save.     Link Value Stream and Begin Storage   Now that we have a Value Stream to act as a storage location, we want to link it to EdgeThing.   After EdgeThing knows where to store historical data, we can simply instruct it which Property we want to archive by setting it to Logged.       1. Return to EdgeThing and its General Information tab.       2. In the Value Stream field, search for and select EEFV_ValueStream.       3. Click Save.       4. Still on EdgeThing, click Properties and Alerts.       5. Click Result_low_grease_mo to trigger the slide-out from the right-side.         6. Check Logged.       7. Click the Check icon in the top-right to close the slide-out.       8. Click Save.     Add Line Chart and Data   As per most guides in this Learning Path, it is assumed that you have an active connection to the EMS Engine Simulator and have your Analytics Event currently set to active.   This provides both the engine-sensor inputs and the analytical results for our Mashup.   After adding the Value Stream above, you'll need to let it run for a bit for the historical data to be archived. After it's run for a while and we have a valid history build-up, you can display that history in a Line Chart.       1. Return to EEFV_Mashup on the Design tab.       2. Click on the top-right section to select it.         3. From the Widgets tab, drag-and-drop a Line Chart onto the top-right section.         4. In the top-right of Mashup Builder, ensure the Data tab is selected.         5. Click the green + button.         6. On the Add Data pop-up in Entity Filter, search for and select EdgeThing.       7. In Services Filter, type queryprop.       8. Click the right arrow button besides QueryPropertyHistory.       9. Check Execute on Load.         10. Click Done.       11. Expand Data > Things_EdgeThing > QueryPropertyHistory > Returned Data.       Bind Data and View Mashup   Now that we have both our method of displaying the historical data, i.e. a Line Chart, as well as a method to bring backend data into the Mashup, i.e. QueryPropertyHistory, we can bind them together and see how our Mashup is progressing.       1. From the right under the Data tab, drag-and-drop EdgeThing > QueryPropertyHistory > Returned Data > All Data onto the Line Chart in the top-right of the Canvas.         2. On the Select Binding Target pop-up, click Data.         3. With the Line Chart selected, explore its Properties in the bottom-left.       4. Change XAxisField to timestamp.         5. Click Save.       6. Click View Mashup.     Your own Line Chart will vary depending on what values your Engine Simulator is sending to Foundation and Analytics.   NOTE: Remember that the Analysis Event needs to be Enabled for new values to be fed into Result_low_grease_mo.     Click here to view Part 3 of this guide.  
View full tip
    Step 3: Modify YourEdgeThingTemplate.lua   Now that the task rate has been decreased to 1000ms (one second), we can create a series of Thing Properties.   In Windows, navigate to C:\CDEMO_EMS\etc\custom\templates.   In your prefered text-editor, open YourEdgeThingTemplate.lua.   We now want to add several lines of Lua code to define some Properties for EdgeThing. You’ll do some with some references that are pre-built into the EMS, primarily the properties structure.   Working with the engine R&D team, their plan is to place two vibration sensors on the proptype engine. In addition, each vibration sensor will have five frequency bands. As such, we’ll need ten Properties to represent the vibration readings.   In addition, we also want a Property that will record whether or not the engine is currently experiencing the low grease condition. This will be entered via manual-inspection at the same time that the frequency readings are recorded.   Perform the following to implement the ten vibration frequency bands and the low grease condition.   Below the module line of YourEdgeThingTemplate.lua, add the following line to create a low_grease Property: properties.low_grease={baseType="NUMBER", pushType="ALWAYS", value=0} Below that, add the following lines to create the five frequency bands for the first vibration sensor: properties.s1_fb1={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb2={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb3={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb4={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb5={baseType="NUMBER", pushType="ALWAYS", value=0} Below that, add the following lines to create the five frequency bands for the second vibration sensor: properties.s2_fb1={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb2={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb3={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb4={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb5={baseType="NUMBER", pushType="ALWAYS", value=0} Your code should now look like the picture below.   The code above adds each new Property to the properties structure, and the name of the Property will be what follows after the “.”, i.e. low_grease, s1_fb1, s1_fb2, etc.   In addition, the baseType defines the type of each Property, in this case, all Numbers.   The pushType of ALWAYS means that there are no restrictions on sending new Property values up to Foundation, and the value of 0 indicates the default value to which each Property will initially be set.   Generate Property Values   Now that we have the Properties defined, we want to add code which will give us different values.   To do so, we’ll define a queryHardware function, and tie the calling of it to the task rate which we had set earlier. This queryHardware function will use random numbers to simulate code that would gather actual data.    Add the following Lua code to define a GetSystemProperties function. Note that this calls a separate queryHardware function which we split out to also be called by the tasks timer. serviceDefinitions.GetSystemProperties( output { baseType="BOOLEAN", description="" }, description { "updates properties" } ) services.GetSystemProperties = function(me, headers, query, data) queryHardware() return 200, true end Add the following Lua code to define queryHardware. Note that Lua’s random number generation requires a new seed on each calling, and the randomseed function is using the built-in os.time function (plus some additional noise created by turning that time into a string and back). function queryHardware() math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) ) local temp = math.random(10) if temp < 6 then properties.low_grease.value=0 properties.s1_fb1.value=161+math.random() properties.s1_fb2.value=180+math.random() properties.s1_fb3.value=190+math.random() properties.s1_fb4.value=176+math.random() properties.s1_fb5.value=193+math.random() properties.s2_fb1.value=130+math.random() properties.s2_fb2.value=200+math.random() properties.s2_fb3.value=195+math.random() properties.s2_fb4.value=165+math.random() properties.s2_fb5.value=190+math.random() else properties.low_grease.value=1 properties.s1_fb1.value=90+math.random() properties.s1_fb2.value=170+math.random() properties.s1_fb3.value=170+math.random() properties.s1_fb4.value=95+math.random() properties.s1_fb5.value=190+math.random() properties.s2_fb1.value=165+math.random() properties.s2_fb2.value=195+math.random() properties.s2_fb3.value=190+math.random() properties.s2_fb4.value=140+math.random() properties.s2_fb5.value=190+math.random() end end Finally, we want to tie the calling of queryHardware to the tasks timer by adding the following code: tasks.refreshProperties = function(me) queryHardware() end   We now have code in our EMS template that not only defines the low grease condition and the five frequency bands of our two vibration sensors, but also generates some values in the ranges that R&D have typically seen in both good grease amount and bad grease amount conditions.   The final Lua code of the YourEdgeThingTemplate.lua file should look like the following:   require "shapes.swupdate" module ("templates.YourEdgeThingTemplate", thingworx.template.extend) properties.low_grease={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb1={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb2={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb3={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb4={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb5={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb1={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb2={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb3={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb4={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb5={baseType="NUMBER", pushType="ALWAYS", value=0} serviceDefinitions.GetSystemProperties( output { baseType="BOOLEAN", description="" }, description { "updates properties" } ) services.GetSystemProperties = function(me, headers, query, data) queryHardware() return 200, true end function queryHardware() math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) ) local temp = math.random(10) if temp < 6 then properties.low_grease.value=0 properties.s1_fb1.value=161+math.random() properties.s1_fb2.value=180+math.random() properties.s1_fb3.value=190+math.random() properties.s1_fb4.value=176+math.random() properties.s1_fb5.value=193+math.random() properties.s2_fb1.value=130+math.random() properties.s2_fb2.value=200+math.random() properties.s2_fb3.value=195+math.random() properties.s2_fb4.value=165+math.random() properties.s2_fb5.value=190+math.random() else properties.low_grease.value=1 properties.s1_fb1.value=90+math.random() properties.s1_fb2.value=170+math.random() properties.s1_fb3.value=170+math.random() properties.s1_fb4.value=95+math.random() properties.s1_fb5.value=190+math.random() properties.s2_fb1.value=165+math.random() properties.s2_fb2.value=195+math.random() properties.s2_fb3.value=190+math.random() properties.s2_fb4.value=140+math.random() properties.s2_fb5.value=190+math.random() end end tasks.refreshProperties = function(me) queryHardware() end       Step 4: Modify EdgeThing   Now that our EMS has been updated with Properties, as well as code to generate values for those Properties, we want to re-connect the EMS to Foundation and update the EdgeThing.   Note once again that EdgeThing was previously created in the Use the Edge MicroServer (EMS) to Connect to ThingWorx guide.   Restart the wsemse.exe program by returning to its PowerShell window and executing the following command: .\wsems.exe   Restart the luaScriptResource.exe program by returning to its separate PowerShell window and executing the following command: .\luaScriptResource.exe   Return to ThingWorx Foundation's EdgeThing. Note that EdgeThing is connected.   On the Properties and Alerts tab, click Manage Bindings.   At the bottom-left of the Manage Bindings pop-up, click + Add all properties.   At the bottom-right of the pop-up, click Done.   At the top, click Save.   Near the top, click Refresh repeatedly. Note that the Property values consistently change.          Click here to view Part 3 of this guide.
View full tip
  Enhance your Engine Failure-Prediction GUI.     GUIDE CONCEPT   This guide will use ThingWorx Foundation’s Mashup Builder to create a more advanced Graphical User Interface (GUI) than the one we originally created to display results from Analytics Manager’s engine-failure predictions.   Following the steps in this guide, you will learn how to utilize Widgets and backend data to more completely visualize customer failure conditions.       YOU'LL LEARN HOW TO   Create a Mashup with a Header Divide your Mashup into Sub-sections Use a Contained Mashup to reuse development Store historical data in a Value Steam Display historical data in a Time Series Chart Show spreadsheet data via a Grid Widget Tie Mashup controls into the ThingWorx backend   NOTE: The estimated time to complete all parts of this guide is 60 minutes.     Step 1: Scenario   In this guide, we’re taking our previous MotorCo Minimum Viable Product (MVP) Mashup and expanding it.   Our original Mashup showed the results from ThingWorx Analytics as it determined whether or not a low-grease condition was currently present.   The goal of this guide is to create an Enhanced GUI to visualize those predicted “low grease” conditions in a more complete manner.     GUI-creation to visualize analytical model deployment can be extremely helpful for the automative segment in particular. For instance, each car that comes off the factory line could have an EMS constantly sending data from which an analytical model could automatically detect engine trouble.   This could enable your company to offer an engine monitoring subscription service to your customers.   This guide will show you how to visualize the results of an engine analytic model for a smart, connected products play.     Step 2: Create Mashup   Just like in the last guide, we're now going to create a Mashup to visualize ThingWorx Analytics results.   This one is simply going to be more complicated to include additional functionality.   But before we can start designing our GUI, we must first instantiate a Mashup onto which we can place our Widgets.       1. In ThingWorx Foundation, click Browse > Visualization > Mashups.         2. Click + New.       3. On the New Mashup pop-up under Responsive Templates, click Header Only.       4. Click OK.       5. In the Name field, type EEFV_Mashup.       6. If Project is not already set, search for and select PTCDefaultProject.       7. At the top, click Save.       8. At the top, click Design.         Step 3: Set Layout   Now that we’re in Mashup Builder, you can see the separate top-section of the central Canvas area created by our selection of “Header Only” on the New Mashup pop-up.   Unlike the original Mashup where we used Static Positioning, most of this Mashup will continue to use Responsive so that it can grow and shrink as resolution changes on various viewing devices.   To add multiple Responsive Widgets to a Responsive Positioning Mashup, though, you need to create some additional sub-sections. We’ll do so now.       1. In the top-left of Mashup Builder, click the Layout tab.       2. Click the main, bottom section of the Canvas, i.e. the non-header section, to select it.       3. On the Layout tab, click Add Top.       4. With the top-half of the original bottom section still selected, click Add Left.       5. Click in the bottom section to select the bottom-half of the original container.       6. Click Add Left.       7. At the top, click Save.      You now have a Responsive Positioning Mashup with five (5) sub-sections, i.e. :   Header Top-left Top-Right Bottom-left Bottom-right       Step 4: Adjust Header    In this step, we'll outfit the Header sub-section with a company name and logo.       1. Select the top Header section and ensure that you're still on the Layout tab in the top-left.         2. Change the Positioning to Static.       3. In the top-left, select the Widgets tab.       4. Drag-and-drop an Image Widget onto the Header section.       5. Expand the size of the Image Widget by dragging the corners.       6. Drag-and-drop a Label Widget onto the Header section.       7. Expand the size of the Label Widget.       8. With the Label Widget still selected, change the LabelText Property (in the bottom-left) to MotorCo, and hit the keyboard Tab key to lock-in your modification.         9. In the bottom-left, change to the Style Properties tab.       10. Expand Base > Label, and change font-size to 72px.       11. At the top, click Save.   Upload Media Image   We want to set the earlier Image Widget to the company logo.   To do so, we need to upload it to Foundation by creating a Media Entity.       1. Click Browse > Visualization > Media.       2. Click + New.       3. In the Name field, type EEFV_Logo.       4. If Project is not already set, search for and select PTCDefaultProject.       5. Right-click and "Save as" to download motorco-logo.jpg.       6. Under Image, click Change.       7. Navigate to and select the motorco-logo.jpg file you just downloaded.       8. Click Open.       9. At the top, click Save.   Change Image to Logo   Now that we have the company logo stored within ThingWorx, we can update the Image Widget to reference it.       1. Return to EEFV_Mashup.       2. Click the Image Widget to select it, and ensure that the bottom-left Properties tab is active.         3. Scroll down in the Properties until you find SourceURL.         4. In the Search Media field, type eefv.         5. Select EEFV_Logo.         6. Click Save.     Change Background Color   Finally, we want to change the background color of the Header.       1. In the top-left, select the Explorer tab. Note that the Explorer tab may be in the top-left drop-down if you're using a lower-resolution screen.         2. Select the Header itself.         3. In the bottom-left, select the Style Properties tab and expand Base > Container.         4. Beside background, click the white square to open a color-selector.       5. Select a color you desire.         6. Click Select.         7. Click Save.     Click here to view Part 2 of this guide.
View full tip
    Step 5: Tie Data to Widgets   The Mashup now has access to the backend data via get/set Data Services.   In this step, you will tie these Data Services to the Checkbox Widgets to pull and push information.   Click the Data tab in the upper right   Under GetProperties, click and drag the arrow next to Channel2_myPLC_Coil2 onto the Left Checkbox. On the Select Binding Target pop-up, click State.   Click the Data tab again Drag Channel2_myPLC_Coil3 onto the right Checkbox. On the Select Binding Target pop-up, click State.   Enable Automatic Updates   The GetProperties Mashup Data Service will now propagate the State of Coil2 and Coil3 from the PLC onto these Checkbox Widgets.   The GetProperties Service will be called automatically when the Mashup loads, so the Checkboxes states will be accurate on initial viewing.   However, the backend data state changes, you will need the GetProperties Service to be automatically called again to update the Checkbox Widgets.   Fortunately, it is simple to trigger this behavior.   Click the Data tab Click GetProperties to select it.   On the right of the Mashup Builder, Click the Data Properties tab     Click the Automatically Update Values checkbox   Allow Bidirectional Sets   You also want to enable bi-directional communication, not only displaying the current value of the PLC, but also setting it via the Mashup GUI.   The SetProperties Mashup Data Service can accomplish this.   Click the Right Checkbox to select it.   Click the Checkbox Widget's top-left drop-down menu to expose the available options.   Drag State over the Data tab to expand it. Drop onto SetProperties > Channel2_myPLC_Coil3.   Click the right Checkbox drop-down menu again.   Click Configure Bindings.   Click the down arrow to the right of Changed.   Click Add Trigger Service. Click the Data tab. Select the setProperties check box.   Click Next to close the Trigger Services window. Click Done to close the Configure Bindings pop-up. At the top, click Save.     Step 6: View Mashup    Your Mashup is now complete with two Checkbox Widgets and connections from those Widgets to the backend data.   The left Checkbox represents Coil2, and will change its state depending on whether you have touched the lead to the appropriate input on the PLC.   The right Checkbox represents Coil3, and will display the current status as well as allow you to set the status of Output Coil 3 via checking or unchecking the box.   At the top, click View Mashup to display your web application. You may need to set your browser to allow pop-ups.     Select the right checkbox. Note how the PLC's Output Coil 3 will immediately turn on.   Touch the lead to the PLC's I-02, i.e. Input 2. The left checkbox will indicate the status of Input 2 within a couple of seconds. Step 7: Troubleshooting   If the connection to the PLC stops working and there is a Thumbs Down icon next to your properties, the ThingWorx Kepware Server trial edition drivers are not connected to your PLC. The trial edition stops running after 2 hours and must be stopped and restarted. Right-click on ThingWorx Kepware Server icon in system tray.     Click Stop Runtime service. Wait a minute for the process to stop, then click Start Runtime service. If Connected Components Workbench does not connect to PLC, check the IP address of the PLC using RS Linx Classic software that was installed as part of Connected Components Workbench. RS Linx Classic is located Start > All Programs > Rockwell Software > RSLinx > RSLinx Classic Click AB_ETHIP-1, Ethernet and IP addresses of connected PLCs will be discovered NOTE: A changed PLC IP Address (typically seen through Connected Components Workbench) will require an IP Address change in ThingWorx Kepware Server settings.     Step 8: Next Steps   Congratulations! You've successfully completed the Visualize an Allen-Bradley PLC guide.   In addition, assuming you have been utilizing this guide as part of the Rockwell Automation Learning Path, this represents the end of your journey.   You've learned how to:   Create a Mashup Add Widgets Access backend data via Mashup Data Services Tie data to Widgets Create a simple web application that monitors and controls a PLC   This is the last guide in the Using an Allen-Bradley PLC with ThingWorx learning path. Learn More   Capability Resource Analyze Monitor an SMT Assembly Line Additional Resources   For additional information on ThingWorx Kepware Server:   Resource Link Documentation Kepware documentation Support Kepware Support site
View full tip
  Step 6: Record Data   Now that we have a place to permanently store the values coming from the EMS engine simulator, we'll write a Service to take samples and place them within the Info Table.   Part of that Service, though, will be incrementing the identifier, so we'll need to create one last Property.   Ensure that you're on the Properties and Alerts tab of EdgeThing. At the top-left, click + Add.     In the Name field of the slide-out on the right, type identifier. Change the Base Type to NUMBER. Click Persistent. Click Has Default Value. In the Has Default Value field, type 0.   At the top-right, click the "Check" button for Done. At the top, click Save.   Store the Property Values   With all the pieces in place, we can now create our Service to add entries to our Info Table Property.   At the top of EdgeThing, click Services.   At the top-left, click + Add.   On the "+ Add" drop-down, select Local (JavaScript). In the Service Info > Name field, type recordService.     Expand Me/Entities > Properties.     Click the arrow beside infoTableProperty.     Type .AddRow({ after me.infoTableProperty to being the process of calling the "AddRow()" function.     We now have called the function which will add a row of information to the Info Table Property, one entry for each column of the formatting Data Shape.   We just need to specify which values go into which column.   Add the following lines to store the individual Identifier count into the first column of the Info Table Property: identifier:me.identifier, Because we want the identifier in the stored data to increment on each run, and we want to start the count at 1 (and the Default Value is 0), add the following line to the top of the Service: me.identifier=me.identifier+1;       Add the low_grease value with the following line: low_grease:me.low_grease, Add the following lines to store the five frequency bands of the first sensor: s1_fb1:me.s1_fb1, s1_fb2:me.s1_fb2, s1_fb3:me.s1_fb3, s1_fb4:me.s1_fb4, s1_fb5:me.s1_fb5, Add the final lines to store the five frequency bands of the second sensor and close out the AddRow() function: s2_fb1:me.s2_fb1, s2_fb2:me.s2_fb2, s2_fb3:me.s2_fb3, s2_fb4:me.s2_fb4, s2_fb5:me.s2_fb5 }); You completed Service should look like the following: me.identifier=me.identifier+1; me.infoTableProperty.AddRow({ identifier:me.identifier, low_grease:me.low_grease, s1_fb1:me.s1_fb1, s1_fb2:me.s1_fb2, s1_fb3:me.s1_fb3, s1_fb4:me.s1_fb4, s1_fb5:me.s1_fb5, s2_fb1:me.s2_fb1, s2_fb2:me.s2_fb2, s2_fb3:me.s2_fb3, s2_fb4:me.s2_fb4, s2_fb5:me.s2_fb5 });     At the top, click Done. At the top, click Save.       Run the Service   With our Service completed, let's run it to store a sampling of the data coming from our EMS Engine Simulator.   Under the Execute column in the center, on the recordService row, click the "Play" icon for Execute service. At the bottom-right, click Execute.     At the bottom-right, click Done. At the top, click Properties and Alerts.   Under the Value column, on the infoTableProperty row, click the "Pencil" icon for Set value of property.   Note that the Service has captured a snap-shot of the vibration data and grease condition and permanently stored it within the Info Table Property. You now have not only an Engine Simulator that is constantly sending data from a remote EMS, but a way to permanently record data at points that you deem significant.   Feel free to return to the Service and call it several more times. Each time, the values coming from the Engine Simulator will be stored in another entry in the Info Table Property.       Step 7: Next Steps   Congratulations! You've successfully completed the Use the EMS to Create an Engine Simulator guide, and learned how to:   Modify an EMS Template Provision Thing Properties and Values from an EMS rather than Foundation Send information from an EMS to Foundation Store large amounts of data in an InfoTable Property Create a simulator for testing   The next guide in the Vehicle Predictive Pre-Failure Detection with ThingWorx Platform learning path is Engine Simulator Data Storage. Learn More We recommend the following resources to continue your learning experience: Capability Guide Build Engine Simulator Data Storage Build Implement Services, Events and Subscriptions Additional Resources If you have questions, issues, or need additional information, refer to: Resource Link Community Developer Community Forum Support Analytics Builder Help Center  
View full tip
    Step 5: Create InfoTable   Now that we have connected values coming from our EMS engine simulator, we want a method of permanent storage whenever we feel it's appropriate to take a sample.   From repeated sampling, we'll be able to build up a historical record usable for both manual inspection, as well as automatic analysis via ThingWorx Analytics (though ThingWorx Analytics is beyond the scope of this guide).   To hold these records, we'll use an Info Table Property.   But any time that you create an Info Table, you first need a Data Shape to format the columns.   Click Browse > MODELING > Data Shapes.     At the top-left, click + New.   In the Name field, type esimDataShape.     If Project is not already set, search for and select PTCDefaultProject. At the top, click Field Definitions.     We now want to add a separate Field Definition for each entry of our engine simulator data, i.e. low_grease, s1_fb1 through s1_fb5, and s2_fb1 through s2_fb5.   In addition, we'll add an additional field named identifier which simply keeps a rolling count of the current log entry number.   Click + Add.     In the Name field on the right slide-out, type identifier Change the Base Type to NUMBER. Check Is Primary Key   At the top-right, click the "Check with a +" button for Done and Add.     Repeatedly add additional definitions as per the chart below: Note that you will NOT check the "Is Primary Key" box, as you only need one, i.e. identifier. Name Base type low_grease NUMBER s1_fb1 NUMBER s1_fb2 NUMBER s1_fb3 NUMBER s1_fb4 NUMBER s1_fb5 NUMBER s2_fb1 NUMBER s2_fb2 NUMBER s2_fb3 NUMBER s2_fb4 NUMBER Create one additional entry for s2_fb5 and NUMBER, but click the "Check" button for DONE. At the top, click Save.     Create Info Table   Now that we have a Data Shape we can add an Info Table Property to EdgeThing. Return to the Properties and Alerts tab of EdgeThing.   At the top-left, click + Add.   In the Name field of the slide-out on the right, type infoTableProperty.   Change the Base Type to INFOTABLE.   In the new Data Shape field, search for and select esimDataShape.   Check the Persistent checkbox.   At the top-right, click the "Check" button for Done. At the top, click Save.     Click here for Part 4 of this guide.
View full tip
  Use the Edge MicroServer (EMS) to simulate an engine with vibration sensors.   GUIDE CONCEPT   The Edge MicroServer (EMS) facilitates connectivity from Edge devices to ThingWorx Foundation.   It’s often easier, though, to start development with simulated Edge values rather than hooking up sensors.   This guide will show you how to simulate vibration values of an engine using the EMS.     YOU'LL LEARN HOW TO   Modify an EMS Template Provision Thing Properties and Values from an EMS rather than Foundation Send information from an EMS to Foundation Store large amounts of data in an InfoTable Property Create a simulator for testing   NOTE:  The estimated time to complete all parts of this guide is 30 minutes.     Step 1: Scenario   MotorCo manufactures, sells, and services commercial motors.   Recently, MotorCo has been developing a new motor, and they already have a working prototype.   However, they’ve noticed that the motor has a chance to FAIL CATASTROPHICALLY if it’s not properly serviced to replace lost grease on a key moving part.     In order to prevent this type of failure in the field, MotorCo has decided to instrument their motors with sensors which record vibration.   The hope is that these sensors can detect certain vibrations which indicate required maintenance before a failure occurs.   In this guide, you’ll begin this monitoring process by using ThingWorx Foundation to monitor and record vibration data from the prototype motor. In particular, you will learn how to provision Thing Properties and Values from an EMS, as well as how to permanently store these values for analysis in an Info Table Property.   These types of modifications to an EMS can be extremely helpful for the automotive segment in particular. For instance, each car that comes off the factory line could have custom, auto-generated EMS scripting that would dynamically create Foundation information for each car in the fleet. This could be a massive time-savings versus manually generating Thing Properties directly within Foundation.   Because the motor is still in the process of being instrumented with sensors, you’ll get all the functionality in-place beforehand by constructing a motor simulator using the Edge MicroServer (EMS).     Step 2: Modify config.lua   In the previous Use the Edge MicroServer (EMS) to Connect to ThingWorx  guide, you installed the EMS on a Windows PC, configured it to talk to ThingWorx Foundation, and then created an EdgeThing on Foundation to complete the connectivity.   This guide assumes that you have already completed that Windows EMS guide and have an active EMS connection to the EdgeThing.   Perform the following steps to modify this connection to increase the task rate of the EMS, which we'll use in the following steps to update Properties more quickly.   On your Windows PC, select the Windows PowerShell window where the luaScriptResource.exe program is running.   Type Ctrl-C to close the luaScriptResource.exe operation, i.e. hold the Control key and hit the C key.   Minimize the luaScriptResource.exe PowerShell window, and activate the wsemse.exe PowerShell window.   Type Ctrl-C to close the wsems.exe operation.   Return to Foundation, and note that EdgeThing is not connected.   Navigate to the C:\CDEMO_EMSE\etc directory.   Open config.lua in your prefered text-editor.   Change scanRate to 1000. Add the following line below the scanRate line: taskRate = 1000,   The final code of config.lua should be the following Note that the EMS may have slightly modified your config.lua file, such as adding a data_security_key line. Leave these EMS-generated modifications alone. scripts.log_level = "WARN" scripts.script_resource_ssl = false scripts.script_resource_authenticate = false scripts.EdgeThing = { file = "thing.lua", template = "YourEdgeThingTemplate", scanRate = 1000, taskRate = 1000, sw_update_dir = "C:\\CDEMO_EMS\\updates" } Save the config.lua file.     Click here to view Part 2 of this guide.
View full tip
  Step 5: Java - Events   While connected to the server, you can trigger an event on a remote Thing. The code snippet from the Simple Thing example below shows how to use a ValueCollection to specify the payload of an event, and then trigger a FileEvent on a remote Thing.   Create Event   The two implementations of the VirtualThing.defineEvent method are used to create an event definition ThingWorx Platform. @ThingworxEventDefinitions(events = { @ThingworxEventDefinition(name = "SteamSensorFault", description = "Steam sensor fault", dataShape = "SteamSensor.Fault", category = "Faults", isInvocable = true, isPropertyEvent = false) }) public void defineEvent(String name, String description, String dataShape, AspectCollection aspects) { EventDefinition eventDefinition = new EventDefinition(name, description); eventDefinition.setDataShapeName(dataShape); if (aspects != null) { eventDefinition.setAspects(aspects); } this.getThingShape().getEventDefinitions().put(name, eventDefinition); } public void defineEvent(EventDefinition eventDefinition) { this.getThingShape().getEventDefinitions().put(eventDefinition.getName(), eventDefinition); }   Queue Event   To queue an event, create a ValueCollection instance, and load it with the necessary fields for the DataShape of that event. ValueCollection eventInfo = new ValueCollection(); eventInfo.put(CommonPropertyNames.PROP_MESSAGE, new StringPrimitive("Temperature at " + temperature + " was above limit of " + temperatureLimit)); super.queueEvent("SteamSensorFault", DateTime.now(), eventInfo); super.updateSubscribedEvents(60000);   Fire Event   You can send the client a request to fire the event with the collected values, the event, and information to find the entity the event belongs to as shown below. In order to send the Event to the ThingWorx Platform, use the VirtualThing.updateSubscribedEvents method. ValueCollection eventInfo = new ValueCollection(); eventInfo.put(CommonPropertyNames.PROP_MESSAGE, new StringPrimitive("Temperature at " + temperature + " was above limit of " + temperatureLimit)); super.queueEvent("SteamSensorFault", DateTime.now(), eventInfo); super.updateSubscribedEvents(60000);     Step 6: Java - Services   Create Services   Simply use the ThingworxServiceDefinition and ThingworxServiceResult anotations to create a service. Then, you can define the service as shown in this code: @ThingworxServiceDefinition(name = "GetSteamSensorReadings", description = "Get SteamSensor Readings") @ThingworxServiceResult(name = CommonPropertyNames.PROP_RESULT, description = "Result", baseType = "INFOTABLE", aspects = { "dataShape:SteamSensorReadings" }) public InfoTable GetSteamSensorReadings() { InfoTable table = new InfoTable(getDataShapeDefinition("SteamSensorReadings")); ValueCollection entry = new ValueCollection(); DateTime now = DateTime.now(); try { // entry 1 entry.clear(); entry.SetStringValue(SENSOR_NAME_FIELD, "Sensor Alpha"); entry.SetDateTimeValue(ACTIV_TIME_FIELD, now.plusDays(1)); entry.SetNumberValue(TEMPERATURE_FIELD, 50); entry.SetNumberValue(PRESSURE_FIELD, 15); entry.SetBooleanValue(FAULT_STATUS_FIELD, false); entry.SetBooleanValue(INLET_VALVE_FIELD, true); entry.SetNumberValue(TEMPERATURE_LIMIT_FIELD, 150); entry.SetNumberValue(TOTAL_FLOW_FIELD, 87); table.addRow(entry.clone()); // entry 2 entry.clear(); entry.SetStringValue(SENSOR_NAME_FIELD, "Sensor Beta"); entry.SetDateTimeValue(ACTIV_TIME_FIELD, now.plusDays(2)); entry.SetNumberValue(TEMPERATURE_FIELD, 60); entry.SetNumberValue(PRESSURE_FIELD, 25); entry.SetBooleanValue(FAULT_STATUS_FIELD, true); entry.SetBooleanValue(INLET_VALVE_FIELD, true); entry.SetNumberValue(TEMPERATURE_LIMIT_FIELD, 150); entry.SetNumberValue(TOTAL_FLOW_FIELD, 77); table.addRow(entry.clone()); } catch (Exception e) { e.printStackTrace(); } return table; }   NOTE: This service will be callable by the ThingWorx Platform.   Call Services   The are two types of service calls that can be made. The first type belongs to the ConnectedThingClient class. This client has methods for processing information where only the parameters for the method is necessary. The other type of call is based on services located on an Entity. For these calls, you must create a ValueCollection instance, and load it with the necessary parameters of the service.   After loading the ValueCollection instance, send the client the request to execute the service with the:   Parameter values Service name Timeout setting (in milliseconds) for the service to finish executing Information to find the entity the service belongs to   The first type of call can be seen in SimpleClient.java: InfoTable result = client.readProperty(ThingworxEntityTypes.Things, ThingName, "name", 10000); String name = result.getFirstRow().getStringValue("name");   The second type of call can be seen below: ValueCollection payload = new ValueCollection(); payload.put("name", new StringPrimitive("Timothy")); InfoTable table = handleServiceRequest("ServiceName", payload);   TIP: Put the code for creating the service and event in the constructor of the extended VirtualThing (or a method called from the constructor). Also, the service code examples will work as long as the actual service is defined. We recommend the annotation method as shown in the examples because it is much cleaner.       Click here to view Part 5 of this guide.  
View full tip
  Step 5: Import Extension   Now that we have a valid dataset, we want to export it as a .csv file, which can be imported into ThingWorx Analytics in a future guide to generate an analytical model.   An easy way to do this is with the CSV Parser Extension, which you’ll now import.       1. Download the CSV Parser Extension from our third party provider IQNOX.   Note:  An account is required but the download is free.     2. At the bottom-left, click Import/Export.       3. On the drop-down, click Import.       4. For Import Option, select Extension.       5. Click Browse and navigate to the extension you downloaded above.       6. Click Open.       7. Click Import.       8. Click Close.       9. On the Refresh Composer? pop-up, click Yes.      Step 6: Create File Repository   ThingWorx Foundation uses File Repositories to read and write files from disk (including .csv files created by the CSV Parser Extension).   In this step, we’ll create a File Repository Entity.       1. Return to Browse > All.       2. Click MODELING > Things.       3. Click + New.       4. In the Name field, type ESDS_File_Repository.       5. If Project is not already set, search for and select PTCDefaultProject.       6. In the Base Thing Template field, search for and select FileRepository.      7. At the top, click Save.        Step 7: Create .csv Export Service   We have imported an Extension which gives us tools to manipulate .csv files. We have created a File Repository to which the export can save the file. We'll now make use of some of this new functionality.    We’ll do so by creating a Service which calls built-in functions of the CSV Parser Extension.       1. Return to EdgeThing.       2. Click Services.       3. Click + Add.       4. On the drop-down, select Local (JavaScript).       5. In the Name field, type exportCSVservice.       6. In the blank JavaScript field, copy-and-paste the following code:           var sFile = "vibrationCSVfile.csv"; var paramsCSV = { path: sFile, data: me.infoTableProperty, fileRepository: "ESDS_File_Repository", withHeader: true }; Resources["CSVParserFunctions"].WriteCSVFile(paramsCSV);               7. Click Save and Continue. Note that you should NOT click the top Save button, as that will erase your Service.         Step 8: Export the Engine Data   We now have all the tools in place to export the infoTableProperty as a .csv file to our new File Repository.   All that’s left is to call the appropriate functions.       1. Ensure that you’re still on the Services tab of EdgeThing, and have the exportCSVservice open.       2. At the bottom, click Execute.       3. Return to ESDS_File_Repository.       4. Click Services.       5. Scroll down and find the GetFileListingsWithLinks Service.       6. Click the “Play” icon for Execute service.       7. At the bottom-right, click Execute.       8. On the right, click Thingworx/FileRepositories/ESDS_File_Repository/vibrationCSVfile.csv.     9. The .csv export of the vibration data will now be in your local folder to which your browser saves downloads.       Step 9: Next Steps   Congratulations! You've completed the Engine Simulator Data Storage guide, and learned how to:   Create a Timer Subscribe to a Timer to Trigger a Service Generate Mass Amounts of Test Data Import the CSV Parser Extension Create a File Repository Export the Test Data as a Comma-Seperated Values (.csv) file Download from a File Repository   The next guide in the Vehicle Predictive Pre-Failure Detection with ThingWorx Platform learning path is Build an Engine Analytical Model   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Analyze Build a Predictive Analytics Model Build Implement Services, Events, and Subscriptions   Additional Resources   If you have questions, issues, or need additional information, refer to:        Resource Link Community Developer Community Forum Support Analytics Builder Help Center
View full tip
Announcements