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

Community Tip - You can Bookmark boards, posts or articles that you'd like to access again easily! X

IoT Tips

Sort by:
  Step 4: Write Data to External Database   You’ve connected to the database, you’re able to query the database. Now let’s handle inserting new data into the database. The update statements and data shown below are based on the table scripts provided in the download. Examples of how the ThingWorx entity should look can be seen in the SQLServerDatabaseController and OracleDatabaseController entities that you've downloaded   Running an Insert   Follow the steps below to set up a helper service to perform queries for the database. While other services might generate the query to be used, this helper service will be your shared execution service. In the DatabaseController entity, go to the Services tab.     2. Create a new service of type SQL (Command) called RunDatabaseCommand. 3. Keep the Output as Integer. 4. Add the following parameter:   Name Base Type Required command String True         5. Add the following code to your new service:   <<command>>       6. Click Save and Continue. Your service signature should look like the below example.     You now have a service that can run commands to the database. Run your service with a simple insert.   There are two ways to go from here. You can either query the database using services that call this service, or you can create more SQL Command services that query the database directly. Let’s go over each method next, starting with a service to call the helper.   In the Services tab of the DatabaseController entity, create a new service of type JavaScript. Name the service JavaScriptInsert_PersonsTable. Set the Output as InfoTable, but do not set the DataShape for the InfoTable. Add the following code to your new service: try { var command = "INSERT INTO Persons (person_key, person_name_first, person_name_last, person_email, person_company_name, " + "person_company_position, person_addr1_line1, person_addr1_line2, person_addr1_line3, person_addr1_city, person_addr1_state, " + "person_addr1_postal_code, person_addr1_country_code, person_addr1_phone_number, person_addr1_fax_number, person_created_by, " + "person_updated_by, person_created_date, person_updated_date) VALUES ('" + key + "', '" + name_first + "', '" + name_last + "', '" + email + "', '" + company_name + "', '" + company_position + "', '" + addr1_line1 + "', '" + addr1_line2 + "', '" + addr1_line3 + "', '" + addr1_city + "', '" + addr1_state + "', '" + addr1_postal_code + "', '" + addr1_country_code + "', '" + addr1_phone_number + "', '" + addr1_fax_number + "', '" + created_by + "', '" + updated_by + "', '" + created_date + "', '" + updated_date + "')"; logger.debug("DatabaseController.JavaScriptInsert_PersonsTable(): Query - " + command); var result = me.RunDatabaseCommand({command: command}); } catch(error) { logger.error("DatabaseController.JavaScriptInsert_PersonsTable(): Error - " + error.message); }         5. Add the following parameter:   Name Base Type Required key String True name_first String True name_last String True company_name String True company_position String True addr1_line1 String True addr1_line2 String True addr1_line3 String True addr1_city String True addr1_state String True addr1_postal_code String True addr1_country_code String True addr1_phone_number String True addr1_fax_number String True created_by String True updated_by String True created_date String True updated_date String True         6. Click Save and Continue.   Any parameter, especially those that were entered by users, that is being passed into a SQL Statement using the Database Connectors should be fully validated and sanitized before executing the statement! Failure to do so could result in the service becoming an SQL Injection vector.   Now, let’s utilize a second method to create a query directly to the database. You can use open and close brackets for parameters for the insert. You can also use <> as a method to mark a value that will need to be replaced. As you build your insert statement, use [[Parameter Name]] for parameters/variables substitution and <<string replacement >> for string substitution.   1. In the Services tab of the DatabaseController entity, create a new service of type SQL (Command).   2. Name the service SQLInsert_PersonsTable. 3. Add the following code to your new service: INSERT INTO Persons (person_key ,person_name_first ,person_name_last ,person_email ,person_company_name ,person_company_position ,person_addr1_line1 ,person_addr1_line2 ,person_addr1_line3 ,person_addr1_city ,person_addr1_state ,person_addr1_postal_code ,person_addr1_country_code ,person_addr1_phone_number ,person_addr1_fax_number ,person_created_by ,person_updated_by ,person_created_date ,person_updated_date) VALUES ([[key]] ,[[name_first]] ,[[name_last]] ,[[email]] ,[[company_name]] ,[[company_position]] ,[[addr1_line1]] ,[[addr1_line2]] ,[[addr1_line3]] ,[[addr1_city]]]] ,[[addr1_state]] ,[[addr1_postal_code]] ,[[addr1_country_code]] ,[[addr1_phone_number]] ,[[addr1_fax_number]] ,[[created_by]] ,[[updated_by]] ,[[created_date]] ,[[updated_date]]);       4. Add the following parameter:   Name Base Type Required key String True name_first String True name_last String True company_name String True company_position String True addr1_line1 String True addr1_line2 String True addr1_line3 String True addr1_city String True addr1_state String True addr1_postal_code String True addr1_country_code String True addr1_phone_number String True addr1_fax_number String True created_by String True updated_by String True created_date String True updated_date String True         5. Click Save and Continue.   Examples of insert services can be seen in the provided downloads.     Step 5: Executing Stored Procedures   There will be times when a singluar query will not be enough to get the job done. This is when you'll need to incorporate stored procedures into your database design.   ThingWorx is able to use the same SQL Command when executing a stored procedure with no data return and a SQL query when executing a stored procedure with an expected result set. Before executing these services or stored procedures, ensure they exist in your database. They can be found in the example file provided.   Execute Stored Procedure   Now, let's create the service to handle calling/executing a stored procedure.   If you are expecting data from this stored procedure, use EXEC to execute the stored procedure. If you only need to execute the stored procedure and do not expect a result set, then using the EXECUTE statement is good enough. You're also able to use the string substitution similar to what we've shown you in the earlier steps.   In the DatabaseController entity, go to the Services tab. Create a new service of type SQL (Command) called RunAssignStudentStoredProcedure. Add the following parameter:   Name Base Type Required student_key String True course_key String True         4. Add the following code to your new service:   EXECUTE AddStudentsToCourse @person_key = N'<<person_key>>', @course_key = N'<<course_key>>'; You can also perform this execute in a service based on JavaScript using the following code: try { var command = "EXECUTE AddStudentsToCourse " + " @student_key = N'" + student_key + "', " + " @course_key = N'" + course_key + "'"; logger.debug("DatabaseController.RunAssignStudentStoredProcedure(): Command - " + command); var result = me.RunDatabaseCommand({command:command}); } catch(error) { logger.error("DatabaseController.RunAssignStudentStoredProcedure(): Error - " + error.message); }         5. Click Save and Continue.   Execute Stored Procedure for Data   Let's create the entity you will use for both methods. This can be seen in the example below:     In the DatabaseController entity, go to the Services tab. Create a new service of type SQL (Query) called GetStudentCoursesStoredProcedure. Set the Output as InfoTable, but do not set the DataShape for the InfoTable. Add the following parameter:   Name Base Type Required course_key String True         5. Add the following code to your new service:   EXEC GetStudentsInCourse @course_key = N'<<course_key>>'   You can also perform this execute in a service based on JavaScript using the following code:   try { var query = "EXEC GetStudentsInCourse " + " @course_key = N'" + course_key + "'"; logger.debug("DatabaseController.GetStudentCoursesStoredProcedure(): Query - " + query); var result = me.RunDatabaseQuery({query:query}); } catch(error) { logger.error("DatabaseController.GetStudentCoursesStoredProcedure(): Error - " + error.message); }       6. Click Save and Continue.   You've now created your first set of services used to call stored procedures for data. Of course, these stored procedures will need to be in the database before they can successfully run.     Click here to view Part 3 of this guide.
View full tip
  Step 7: Set-up and Run Demo   The ThingWorx Azure IoT Connector download includes a Java application that simulates a device connecting to your Azure IoT Hub. A ThingTemplate is also included and can be imported into ThingWorx.   Import Demo Templates   In ThingWorx Composer, click Import/Export menu, then click From File and browse to ../demo/edgedevice- demo/platform/entities/CPUDemo_AllEntities.xml   Click Import then click Close when the import successful message is displayed. Create a new Thing using the imported template azureDemo1, enter a name for your Thing and click Save. NOTE: You will enter this name in the demo config file in the next step. Configure Demo Application   In the ../demo/edge-device-demo/conf subdirectory, open the edge-device.conf file with a text editor. Edit the deviceId to be the name of the Thing you created in step 3. Edit the iotHubHostName to use the name of your hub plus the domain: azure-devices.net. For example, sample-iot-hub.azuredevices.net. Edit the registryPolicyKey property to use the Primary Key for the registryReadWrite policy in the Azure IoT Hub. Below is an example configuration: azure-edge-device { deviceId = "alstestedgething" iotHubHostname = "alsiot.azure-devices.net" registryPolicyName = "registryReadWrite" registryPolicyKey = "pzXAi2nonYWsr3R7KVX9WuzV/1234567NZVTuScl/Kg=" }   Run Demo Script   Open a shell or Command Prompt, set the EDGE_DEVICE_DEMO_OPTS environment variable to refer to the file you just edited: Linux - export EDGE_DEVICE_DEMO_OPTS="-Dconfig.file=../conf/edge-device.conf" Windows - set EDGE_DEVICE_DEMO_OPTS="-Dconfig.file=../conf/edge-device.conf" Launch the demo from the ../demo/edge-device-demo/bin subdirectory, using the edge-device-demo command. Return to the ThingWorx Composer and open the Properties page of the Azure Thing that you created previously. Click the refresh button to see the properties change every five seconds. Open the azure-iot-demo Mashup and view the Load Average and CPU gauges, and the increases in the values of the Cycle and Uptime fields. NOTE: If the edgedevice-demo is running on Windows, the Load Average does not register.   Step 8: Next Steps   Congratulations! You've successfully completed the Connect Azure IoT Hub to ThingWorx Quickstart. By following the steps in this lesson, you imported a device created in Azure into ThingWorx and saw how data from an Azure device could be used in a ThingWorx Mashup.   Learn More   We recommend the following resources to continue your learning experience:   If you're following the Azure MXChip Development Kit learning path, the next guide is Create a Thing Shape.    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
  Use the ThingWorx Azure IoT Hub Connector with simulated appliances.   Guide Concept   This project will introduce how to integrate ThingWorx with Azure IoT Hub. The combination of these two platforms extends the ThingWorx utilities to Azure IoT Hub edge devices and allows integration with Azure Blob Storage accounts.   Following the steps in this guide, you will install the ThingWorx Azure IoT Hub Connector and run a simulated Azure device.   We will teach you how to build powerful and scalable IoT applications by integrating ThingWorx and Azure IoT Hub.   You'll learn how to   Install, configure, and run the ThingWorx Azure IoT Hub Connector Import devices that exist in Azure into ThingWorx Connect a simulated Azure device to ThingWorx Foundation server   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 60 minutes       Step 1: Overview Diagram   The ThingWorx Azure IoT Hub Connector maintains a network connection to both an Azure IoT and a ThingWorx Foundation instance:        The ThingWorx Azure IoT Hub Connector enables remote devices that connect to the Azure IoT Hub, to connect to the ThingWorx Foundation server. The Azure IoT Connector handles message routing for the devices that communicate through the Azure IoT system. It also handles message routing from the ThingWorx Foundation server to devices via the Azure IoT Hub.   The ThingWorx Azure IoT Connector is a separate, stand-alone application that must be run on a server that can connect to both the ThingWorx server and the Azure IoT service.     Step 2: Configure Azure IoT Hub   In order to use the ThingWorx Azure IoT Connector, you must first configure an IoT Hub and a storage account in Microsoft Azure. You can provision a free tier account for these resources. In this step, we will create the Azure resources and gather the configuration information that enable you to connect to ThingWorx with the required credentials.   Log into Azure Portal   If you do not already have an Azure account you can create a free account that will work with this guide.   Create Azure IoT Hub   Follow the Microsoft documentation to create an Azure IoT Hub, accepting any defaults.   TIP: The name your IoT Hub must be globally unique and include only lowercase letters and numbers.   1. Create message routes to direct DeviceLifecycleEvents and TwinChangeEvents events to the built-in events endpoint. For a tutorial, refer to Tutorial: Use the Azure CLI and Azure portal to configure IoT Hub message routing 2. Register at least one Azure IoT Device or Azure IoT Edge Device to your Azure IoT Hub. For a tutorial, refer to Register an IoT Edge device in IoT Hub     Create Storage Account   Follow the Microsoft documentation to create an Azure Storage account.   NOTE: Select Blob storage as the account type and the Hot Access Tier.       Step 3: Import Extensions   The ThingWorx Azure IoT Hub Connector distribution bundle comes packaged with all the software you will need to connect ThingWorx and Azure. Download the Azure IoT Hub Connector from PTC Support Extract the application bundle to a directory on the system where it will run. (where v.v.v represents the release number) On Linux, this guide uses the base directory, /opt. The subdirectories and files should reside in the directory, /opt/ThingWorx-Azure-IoTHub-Connector-4.2.0. On Windows, extract the bundle so that the subdirectories and files reside in C:\ThingWorx-Azure-IoT-Hub-Connector-4.2.0 In the lower-left side of Composer, click Import/Export, then Import.  In the Import From File pop-up, under Import Option select Extension from the drop-down, then click Browse. Navigate to the /extensions directory and click on ConnectionServicesExtension-2.2.4.zip file.   Click Import in the Import From File pop-up, then click Close after file is successfully imported. Repeat the above steps for the azure-iot-hub-adapter-extension-4.2.0.4.zip file. Follow the steps to Create an Application Key and note the value, it will be used in the the next step.     Step 4: Install Azure Connector   Configure Connection Server   The Connection Server component of ThingWorx Azure IoT Connector must be configured with information specific to both your Azure IoT Hub and your ThingWorx Foundation server.   Copy the file azure-iot-sample.conf in the connector > conf directory and save the file with the name azure-iot.conf Edit the configuration file to replace the ten placeholder values for the parameters listed below with values copied from your Azure control panel. consumerPolicyName - Whether you have a new or existing hub, you need to provide the name of the consumer policy and its related Primary or Secondary key. The policy to select is typically the built-in, pre-defined policy called service. Navigate to All Resources > your hub > Settings > Shared access policies > service. If you added a custom service policy to your hub with the permission service connect select that policy.   consumerPolicyKey - Once you find the policy name, stay in the Shared access policies screen, and click the name. Copy the content of the Primary key. This key supplies the credentials to access services that are specified in the related policy. registryPolicyName - Specify a policy name that is related to the registryPolicyKey. This policy is typically a built in, predefined policy called registryReadWrite, but it is possible to use a custom policy if you add it to your hub. The shared access policy requires the registry read and registry write permissions. registryPolicyKey - The key that supplies credentials to access services in the policy specified in registryPolicyName. hubName - A name that defines the Azure IoT Hub related to this ThingWorx Connector. This Azure IoT Hub manages your things and their related messages. Hubs can be scaled via hub units at different price tiers per unit. Hubs are related to a resource group, which is related to a subscription Id and a cloud Location. TIP: To find the name associated with your Azure IoT Hub that the ThingWorx Connector will use to communicate with it, navigate to All Resources > your hub > Settings > Properties > NAME eventHubName - The Event Hub-compatible name that is used by SDKs and integrations that expect to read from Event Hubs. An Event Hub is an internal component of an Azure IoT Hub that handles device-to-cloud events for related things. In many cases, the IoT Hub name and Event Hubcompatible name are the same, so this property defaults to the Azure IoT Hub name (hubName). Navigate to All Resources > your hub > Settings > Built-in endpoints > Events > Event Hub-compatible name to find this name.   eventHubNamespace - To find the endpoint that is used by SDKs and integrations that expect to read from Event Hubs, navigate to All resources > your hub > Settings > Built-in endpoints > Events > Event Hub-compatible endpoint, and copy the host name, without the rest of the address (".servicebus.windows.net"). The ThingWorx Azure IoT Connector uses this endpoint to read messages from your hub. consumerGroup - To find a consumer group name to enable the Connector to pull data from the Azure IoT Hub, navigate to All Resources > your hub > Messaging > Endpoints > Built-in endpoints > Events > Consumer groups. To use the $Default consumer group, set this property to null. hubHostname - To find the host name for your hub, navigate to All Resources > your hub > Overview > Hostname. The host name is defined by the hubName plus a domain name that is chosen by Azure, typically azuredevices.net.   blob-storage.account-name - The blob-storage section specifies the settings for an Azure blob storage account. The storage provides containers that are used for device export of an Azure IoT Hub to ThingWorx via the Connector and can also be created by the Connector if you create AzureStorageContainerFileRepository things in ThingWorx. If you do not have one, create a Storage Account in the Azure portal. To find the name of an existing account, navigate to Settings > Access Keys > Storage account name.   blob-storage.account-key - The key to associate with the name of the blob storage account. To find the key for an existing account, navigate to Settings > Access Keys > Primary or secondary key Enter your ThingWorx Foundation server host, port, and appKey  in the transport.websockets section. transport.websockets { app-key = "6d70dfca-fe88-4d8c-83aa-686449b52cb2" platforms = "ws://45.23.12.112:80/Thingworx/WS" }   NOTE: If you are using an SSL connection to your ThingWorx Foundation server use wss in place of ws in the platform parameter. If the URL for the ThingWorx Foundation server does not include a port, use 80 for http connections and 443 for https.       Step 5: Launch IoT Hub Connector   Open a shell or a command prompt window. On a Windows machine, open the command prompt as Administrator. The AZURE_IOT_OPTS environment variable must be set before starting the Azure IoT Hub Connector. Below are sample commands using the default installation directory. On Windows: set AZURE_IOT_OPTS=-Dconfig.file=C:\ThingWorx-Azure-IoT-Connector-<version>\azure-iot-<version>-application\conf\azure-iot.conf -Dlogback.configurationFile=C:\ThingWorx-Azure-IoT-Connector-<version>\azure-iot-<version>-application\conf\logback.xml On Linux: export AZURE_IOT_OPTS="-Dconfig.file=/var/opt/ThingWorx-Azure-IoT-Connector-<version>/azure-iot-<version>-application/conf/azure-iot.conf -Dlogback.configurationFile=/var/opt/ThingWorx-Azure-IoT-Connector-<version>/azure-iot-<version>-application/conf/logback.xml" NOTE: You must run the export command each time you open a shell or command prompt window. Change directories to the bin subdirectory of the Azure IoT Hub Connector installation. Start the Azure IoT Hub Connector with the appropriate command for your operating system. On Windows: azure-iot.bat On Linux: /azureiot NOTE: On Windows you may have to shorten the installation directory name or move the bin directory closer to the root directory of your system to prevent exceeding the Windows limit on the classpath length.   The Connection Server should start with no errors or stack traces displayed. If the program ends, check the following: Java version is 1.8.0, update 92 or greater and is Java(TM) not OpenJDK. Open azure-iot.conf and confirm ThingWorx Foundation is set to the correct URL and port. Confirm the platform scheme is ws if http is used to access ThingWorx. Confirm all Azure credentials are correct for your Azure account. In ThingWorx Foundation click the Monitoring tab then click Connection Servers. You should see a server named azure-iot-cxserver-{server-uuid}, where {server-uuid} is a unique identifier that is assigned automatically to the server.       Step 6: Import Device from Azure   With the ThingWorx Azure IoT Connector, you can import into ThingWorx any existing devices that are currently provisioned to the Azure IoT Hub.   Add Device Azure IoT Hub   If you have not provisioned any devices to your Azure IoT Hub you can learn more about Azure IoT Hub device identity before following the steps below to create a test device.   In your Azure Portal, click All Resources, then select the name of your IoT Hub. Under Explorers click IoT devices, then click + Add. Enter a name for your device, then click Save. When the device name appears in the list it is ready to use.   Import Device into ThingWorx   We will manually execute a service in ThingWorx that will import Azure IoT Hub devices into ThingWorx.   In ThingWorx Composer, navigate to the ConnectionServicesHub Thing. Click Services tab and scroll to the ImportAzureIotDevices service and click the execute Arrow. NOTE: The * in the pattern field will act as a wildcard and import all devices, you can enter a string to match that will only import a subset of all available devices. Click Execute to import the devices then click Done. Click Things in the left column to see the Things that were created.   Click here to view Part 2 of this guide.
View full tip
  Connect to an existing database and design a connected data model.   GUIDE CONCEPT   There are times you already have your database designed and only need to integrate the ThingWorx environment.   These concepts and steps will allow you to focus on development of your application while still allowing the ability to utilize the power of ThingWorx!   We will teach you how to create a data model around your database design and connect to that database.     YOU'LL LEARN HOW TO   How to connect an external database and created services to be used with it How to design and implement a new data model based on an external resource Using data models with database services   Note: The estimated time to complete this guide is 30 minutes.      Step 1: Examples and Strategy   If you’d like to skip ahead, download and unzip the completed example of the Aerospace and Defense learning path attached to this guide:  AerospaceEntitiesGuide1.zip.   By now, you likely know how to create a data model from scratch. You have likely already created services that work with Info Tables. What you might not have completed, is combining both a new data model, handling data in services, and connecting it all to an external database.   Our organization, PTC Defense Department, has existed for years and has an existing database setup. Developers in our organization refuse to remodel the database, so we must model the ThingWorx data model to our database schema. With ThingWorx, this is not a difficult task, but there are numerous decisions and options that we will explore in this guide.     Step 2: Database Connections   ThingWorx is based on the Java programming language and can make connections to any database that supports a Java-based connection. Dropping the JAR file for the database JDBC driver to the lib folder of Tomcat is all that is needed for connection to the ThingWorx Platform. Follow the below steps to get started creating the connection.   To establish the connection and begin working with an external database, you will need to create a Database Thing and configure the connection string and credentials. Let us start with our database connection. If you have not done so already, download the Aerospace and Defense database scripts: DatabaseApplication.zip. Use the README.txt file to create the database schema. It is based on Microsoft SQL Server, but you can configure the scripts to your database preferences.   NOTE: You will not need to connect to a database to utilize this guide as a learning utility. For your services to work, you will need to connect to a database.   1. In ThingWorx Composer, click the + New at the top-left of the screen.     2. Select Thing in the dropdown.     3. Name the Thing `DatabaseController.Facilities` and select Database as the Base Thing Template.     4.Click Save and go to the Configurations tab.   In this tab, you will enter the class name of your driver, the connection string for that database connection, and the credentials to access the database.   Keep in mind, the JDBC Driver Class Name, JDBC Connection String, and the connection Validation String values are all database type specific. For example, to connect to a SQL Server database, the below configuration can be used.   Title Description  Example   JDBC Driver Class Name  The specific class name of the driver being used for the connection.  net.sourceforge.jtds.jdbc.Driver (SQL Server) or oracle.jdbc.driver.OracleDriver (Oracle)  JDBC Connection String  The connection string to locate the database by host/port/database name.  jdbc:jtds:sqlserver://server:port/databaseName (SQL Server) or jdbc:oracle:thin:@hostname:port:databaseName (Oracle)  connectionValidationString  A simple query that should always work in a database.  SELECT GetDate() (SQL Server) or SELECT SYSDATE FROM DUAL (Oracle)   5. After entering credentials, click Save.     6. Go the Properties and Alerts tab.   The connected Property should be checked. This property informs us of the current connection to the database. The lastConnection Datetime Property should show a current timestamp. This property informs us of the last time there was a valid connection to the database. This is an easy way to confirm the connection to the database.   If you do not have a connection, work on your configurations in the Configurations tab and validate the credentials being used. If you are still having troubles, see the examples section below or use the next section for help to try a query of the database.   Help and Troubleshooting   For help finding the correct configuration for you, check out these JDBC Configuration Examples or try out this Connection String Reference for help with your connection string.   You have just established your first database connection! Now jump to the next section and let us begin to build a data model to match the database schema.   Step 3: Query Data from External Database   Now that you're connected to the database, you can begin querying the database for information and the flow of data. The queries and data shown below are based on the table scripts provided in the download.   Examples of how the ThingWorx entity should look can be seen in the SQLServerDatabaseController and OracleDatabaseController entities.   Running a Query   As you may have noticed by working in ThingWorx and developing applications, an InfoTable is often used to work with large sets of data. An InfoTable is also how data is returned from a database query. If you're expecting only 1 value in the result set, the data will be held in the first index of the InfoTable. If you're expecting rows of data coming back, expect there to be rows of information inside of the InfoTable.   Follow the steps below to set up a helper service to perform queries for the database. While other services might generate the query to be used, this helper service will be a shared execution service.   In the DatabaseController entity, go to the Services tab. Create a new service of type SQL (Query) called RunDatabaseQuery.           3. Set the Output as InfoTable, but do not set the DataShape for the InfoTable.       4. Add the following parameter: Name Base Type Required query String True       5. Add the following code to the new service:   <<query>>       6. Click Save and Continue. Your service signature should look like the below example.       You now have a service that can run queries to the database. This is also a simple method to test/troubleshoot the database connection or a quick query.   Run your service with a simple query. You might notice that no matter the fields in the result set, the InfoTable will match it based on field type and field name.   There are two ways you can go from here. You can either query the database using services that call this service, or you can create more SQL command services that query the database directly. Let's go over each method next, starting with a service to call our helper.   In the Services tab of the DatabaseController entity, create a new service of type JavaScript. Name the service JavaScriptQuery_PersonsTable. Set the Output as InfoTable, but do not set the DataShape for the InfoTable. Add the following code to your new service: try { var query = "SELECT * FROM Persons"; logger.debug("DatabaseController.JavaScriptQuery_PersonsTable(): Query - " + query); var result = me.RunDatabaseQuery({query:query}); } catch(error) { logger.error("DatabaseController.JavaScriptQuery_PersonsTable(): Error - " + error.message); }       5. Click Save and Continue.   Any parameter, especially those that were entered by users, that is being passed into an SQL Statement using the Database Connectors should be fully validated and sanitized before executing the statement! Failure to do so could result in the service becoming an SQL Injection vector.   This is a simple way to query the database since much of your development inside of ThingWorx was already based in JavaScript.   Now, let's utilize the second method to create a query directly to the database. You can use open and close brackets to create parameters for your query. You can also use <> as a method to mark a value that will need to be replaced. As you build your query, use [[Parameter Name]] for parameters/variables substitution and <> for string substitution.   In the Services tab of the DatabaseController entity, create a new service of type JavaScript. Name the service SQLQuery_GetPersonByEmail. Ensure the Output is InfoTable. Add the following code to your new service: SELECT * FROM Persons WHERE person_email = [[email]];       5. Add the following parameter:   Name Base Type Required email String True         6. Click Save and Continue.   An example of using the string replacement is as follows: DELETE FROM <> WHERE (FieldName = '[[MatchName]]'); DELETE FROM << TableName >> WHERE ( FieldName = [[MatchNumber]]);       Click here to view Part 2 of this guide.
View full tip
    Step 8: Tasks   If you are using the built-in Tasker to drive data collection or other types of repetitive or periodic activities, create a function for the task. Task functions are registered with the Tasker and then called at the rate specified after they are registered. The Tasker is a very simple, cooperative multitasker, so these functions should not take long to return and most certainly must not go into an infinite loop.   The signature for a task function is found in [C SDK HOME DIR]/src/utils/twTasker.h. The function is passed a DATETIME value with the current time and a void pointer that is passed into the Tasker when the task is registered. After creating this function, it will need to be registered using the twApi_CreateTask function after the connection is created. Below shows an example of creating this function, registering this function, and how this function can be used.   #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("message", msg, TRUE); twApi_FireEvent(TW_THING, thingName, "SteamSensorFault", faultData, -1, TRUE); twInfoTable_Delete(faultData); } /* Update the properties on the server */ sendPropertyUpdate(); } … twApi_CreateTask(DATA_COLLECTION_RATE_MSEC, dataCollectionTask); … while(1) { char in = 0; #ifndef ENABLE_TASKER DATETIME now = twGetSystemTime(TRUE); twApi_TaskerFunction(now, NULL); twMessageHandler_msgHandlerTask(now, NULL); if (twTimeGreaterThan(now, nextDataCollectionTime)) { dataCollectionTask(now, NULL); nextDataCollectionTime = twAddMilliseconds(now, DATA_COLLECTION_RATE_MSEC); } #else in = getch(); if (in == 'q') break; else printf("\n"); #endif twSleepMsec(5); }      Step 9: File Transfer Example    To handle file transfers, a virtual directory is created in the SteamSensor1 entity and in the [C SDK HOME DIR]/examples/FileTransferExample application directory. The source code used for this example is found in [C SDK HOME DIR]/examples/FileTransferExample/src/main.c.   Inside of the [C SDK HOME DIR]/examples/FileTransferExample folder, create the folder structure shown below: /transfer/ /transfer/incoming/ /transfer/outgoing/ Inside of the /transfer/outgoing/ directory, create and open a file with the name outgoing.txt. Once the outgoing.txt document is open, add the following text, save, and close the file: Hello. This is a file coming from the client application. Navigate to the [C SDK HOME DIR]/examples/FileTransferExample/src/main.c code and update the lines below with the appropriate information for your IP, port, and the “admin_key” Application Key’s keyId value in the ThingWorx Composer: /* Server Details */ #define TW_HOST "127.0.0.1" #define TW_PORT 80 #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c" To support file transfers in your client application, you must use the twFileManager_AddVirtualDir function in order to create the virtual directories in the entity with such a capability. It will also define the directories available for file operations. A virtual directory maps a unique name to an absolute path of a directory in the file system. All subdirectories of the specified directory are exposed to the server. You can define multiple virtual directories. The directories do not need to be contiguous.   Staging Directory   As an optional, but recommended step, you should set the directory that the application should use for staging when performing file transfers. This can be seen in the line below and should be done before initializing the FileManager. The default directory of the FileManager is most likely owned by root and will require a change to either the location of the staging directory and the ownership of the staging directory, or running the application as a User with the correct permissions.   twcfg.file_xfer_staging_dir = "staging"; The example provided uses the TW_SHARE_DIRECTORY macro to create two virtual directories that will act as the root directories in the virtual file system of this application are added. The client is then started as follows with the necessary TW_ADD_FILE_TRANSFER_SHAPE function being called: TW_ADD_FILE_TRANSFER_SHAPE(); TW_SHARE_DIRECTORY("in", "/transfer/incoming/"); TW_SHARE_DIRECTORY("out", "/transfer/outgoing/"); The creations of the payloads used to create the remote directories on the platform have been moved to a helper function below to make the design cleaner: int setupSystemRepo(const char * remoteInPath, const char * remoteOutPath, const char * remoteFile); After our remote directories and files have been setup, it is time to perform the file transfers. Normally, this would mean invoking the Copy service for a Subsystem, but two functions have been created to make this process easier: int twFileManager_GetFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid) int twFileManager_SendFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid) The table below displays an example of the first set of parameters:    Parameter     Example                             Description sourceRepo SystemRepository The name of FileRepository or RemoteThing to transfer the file FROM. sourcePath outgoing The path specifying the location of the source file. sourceFile The name of the source file.   targetRepo SteamSensor1 The name of FileRepository or RemoteThing to transfer the file TO. targetPath incoming The path specifying the destination location of the file. targetFile incoming.txt The name of the file at the target. This name can differ from the sourceName. timeout 15,000 The amount of time (in seconds) to wait for a synchronous transfer to complete before cancelling the transfer. async false If false, the service call will block for timeout seconds or until the transfer completes. tid incoming0123 The unique TID associated with the file.   The C SDK also provides the ability to create a FileCallback function that the FileManager will call that function when any file transfer events occur. You can provide a wildcard filter so that only file transfer Events of files that match the filter call the callback function. In addition, callbacks can be set up as “one-shots” such that the callback is unregistered automatically after it is invoked the first time.   NOTE: An optional file transfer callback is registered in the code and provided. You will see the output from the function as files are sent and received.   After running this application, you will notice a new file in the transfer/incoming folder after refreshing. This is the file that we created in the ThingWorx Composer file system for the SystemRepository Entity and was able to copy from that location to our local project. We have also sent a file to the server’s SystemRepository. The BrowseFileSystem and GetFileListing services can be used to check for the folders and files created.   twFileManager_RegisterFileCallback(fileCallbackFunc, NULL, FALSE, NULL);     Step 10: Support Other Platforms   All Websocket errors indicate some general issue communicating with the ThingWorx platform. If you experience an issue connecting, refer to the table below for a list of websocket errors, their corresponding codes, and an explanation of the issue.    Code     Message                                                                      Troubleshooting 200 TW_UNKNOWN_WEBSOCKET_ERROR An unknown error occurred on the websocket. 201 TW_ERROR_INITIALIZING_WEBSOCKET An error occurred while initializing the websocket. Check your websocket configuration parameters for validity. 202 TW_TIMEOUT_INITIALIZING_WEBSOCKET A timeout occurred while initializing the websocket. Check the status of the connection to ThingWorx. 203 TW_WEBSOCKET_NOT_CONNECTED The websocket is not connected to ThingWorx. The requested operation cannot be performed. 204 TW_ERROR_PARSING_WEBSOCKET_DATA An error occurred while parsing websocket data. The parser could not break down the data from the websocket. 205 TW_ERROR_READING_FROM_WEBSOCKET An error occurred while reading data from the websocket. Retry the read operation. If necessary, resend the data. 206 TW_WEBSOCKET_FRAME_TOO_LARGE The SDK is attempting to send a websocket frame that is too large. The Maximum Frame Size is set when calling twAPI_Initialize and should always be set to the Message Chunk Size (twcfg.message_chunk_size). 207 TW_INVALID_WEBSOCKET_FRAME_TYPE The type of the frame coming in over the websocket is invalid. 208 TW_WEBSOCKET_MSG_TOO_LARGE The application is attempting to send a message that has been broken up in to chunks that are too large to fit in a frame. You should not see this error. 209 TW_ERROR_WRITING_TO_WEBSOCKET An error occurred while writing to the Web socket. 210 TW_INVALID_ACCEPT_KEY The Accept key sent earlier from ThingWorx is not valid.     Step 11: Next Steps   Congratulations! You've successfully completed the Low Level Device Connect Guide, and learned how to utilize the resources provided in the Edge SDK to create your own application.   The next guide in the Utilizing ThingWorx to Secure Your Aerospace and Defense Systems learning path is Tracking Activities and Statistics.    Learn More   We recommend the following resources to continue your learning experience:    Capability      Guide Build Design Your Data Model Build Implement Services, Events, and Subscriptions   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support C Edge SDK Help Center      
View full tip
  Step 6: Create OPC UA Tag in ThingWorx   We will now create a Device in Kepware with a Tag whose value will be shown in ThingWorx.   Right-click on Channel1 that was just created, then click Next to accept the default name Device1       Click Next six times to accept the default settings, Then click the Select import items button.     Expand the remote OPC UA server URL, then expand OpcPlc and Telemetry.     Click SlowUint1 to select it, then click Add items >>. Click OK, Next, Finish. Return to ThingWorx Composer. Under Browse > Modeling > Industrial Connections, open IndConn_Server. Expand Channel1 > Device1 > OpcPlc, then click Telemetry.     Click the check-box next to SlowUint1. Click Bind to New Entity.     Select RemoteThing, then click OK. Enter azure-opcua-plc in the Name field, then click Save.     Click Properties and Alerts, then Click Refresh to see the property value changing every 10 seconds.     Step 7: Next Steps   Congratulations! You've successfully completed the Connect to an Azure OPC UA Server guide, and learned how to:   Create an OPC UA Server in Azure Configure Kepware as on OPC UA Client Connect Kepware to ThingWorx Foundation Monitor OPC UA data in ThingWorx Composer   Learn More   We recommend the following resources to continue your learning experience: Capability Guide Experience Create Your Application UI   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Getting Started with ThingWorx Documentation Kepware documentation Support Kepware Support site
View full tip
  Utilize the C SDK to build an app that creates a secure connection to ThingWorx with low level device access.   Guide Concept   This project will cover using the ThingWorx C SDK to develop applications for the purpose of secure and low level development.   Following the steps in this this guide, you will be ready to develop your own IoT application with the ThingWorx C SDK.   We will teach you how to use the C programming language to connect and build IoT applications to be used with the ThingWorx Platform.       You'll learn how to   Establish and manage a secure connection with a ThingWorx server, including SSL negotiation and connection maintenance. Enable easy programmatic interaction with the Properties, Services, and Events that are exposed by Entities running on a ThingWorx server. Basic concepts of the C Edge SDK How to create an application that can communicate with other devices   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL parts of this guide is 60 minutes       Step 1: Completed Examples   Download the completed files attached to this tutorial: C_SDK.zip.   This tutorial will guide you through working with the C SDK on differing levels. Utilize this file to see a finished example and return to it as a reference if you become stuck creating your own fully flushed out application. With the C SDK, you can connect to whatever device you have at a level most programming languages wouldn't be able to. Now think of your secure system, your fighter jet, or even you communication devices. All these systems and levels need to have a way to secure transfer data and the C SDK is how we do it.   Keep in mind, this download uses the exact names for entities used in this tutorial. If you would like to import this example and also create entities on your own, change the names of the entities you create.     Step 2: Environment Setup   In order to compile C code, download the attached C compiler: C-SDK-2-2-12-1052.zip.    Operating System          Notes Windows You will need a 3rd party compiler such as MinGW GCC, Cygwin GCC or you can follow these Microsoft instructions to download and use the Microsoft Visual C++ Build Tool. Mac Download the Apple Developer Tools. Linux/Ubuntu A compiler is included by default.   NOTE: You can use CMake, version 2.6.1 or later to build projects or make files, which then are used to build the applications that you develop with the C SDK. Before you can begin developing with the ThingWorx C SDK, you need to generate an Application Key and modify the source code file. You can use the Create an Application Key as a reference.   Modify Source File   Extract the files from the C SDK samples zip file. At the top level of the extracted files, you will see a folder called examples, which provides examples of how to utilize the C SDK. Open a terminal, go to your workspace, and create a new project. After you've created this project in your workspace, import the entire C SDK downloaded from the PTC Support site for ease of use (mainly the src folder and the CMakeList.txt file). You can start creating your connection code or open the main.c source file in the examples\SteamSensor\src directory for an example.    Operating System        Code Linux/Ubuntu gedit main.c OR vi main.c Mac open –e main.c Windows start main.c   5. Modify the Server Details section at the top with the IP address for your ThingWorx Platform instance and the application key you would like to use. Change the TW_HOST definition accordingly. Change the TW_PORT definition accordingly. Change the TW_APP_KEY definition to the keyId value saved from the last step. /* Server Details */ #define TW_HOST "https://pp-XXXXXXXXX.devportal.ptc.i" #define TW_PORT 80 #define TW_APP_KEY "e1d78abf-cfd2-47a6-92b7-37dc6dd34618" NOTE: Using the Application Key for the default Administrator is not recommended. If administrative access is absolutely necessary, create a user and place the user as a member of Admins.   Compile and Run Code   To test your connection, you will only need to update the main.c in the SteamSensor example folder.   CMake can generate visual studio projects, make build files or even target IDEs such as Eclipse, or XCode. CMake generates a general description into a build for your specific toolchain or IDE.   If you have not downloaded and installed CMake, do it now at the CMake website. NOTE: CMake comes as a command line and a GUI application. The steps in this guide use the command line version only. Inside the specific example folder you would like to run, ie SteamSensor. Create a directory to build in, for this example call it cmake. mkdir cmake cd cmake 4. Run the CMake command listed below. This assumes CMake is already on your PATH. cmake -G "Visual Studio 15 2012" .. 5. CMake has now produced a set of project files which should be compatible with your development environment.  Operating System    Command                                        Notes Unix command-> make A set of make files Windows **msbuild tw-c-sdk.sln /t:build** A visual studio solution NOTE: CMake does its best to determine what version of Visual Studio you have but you may wish to specify which version to use if you have more than one installed on your computer. Below is an example of forcing CMake to use a specific version of Visual Studio: cmake -G "Visual Studio 15 2017" .. If your version of Visual Studio or other IDE is unknown, use cmake -G to see a list of supported IDEs.   You also have the alternative of opening the tw-c-sdk.sln from within Visual Studio and building in this IDE.   NOTE: By default, CMake will generate a build for the creation of a release binary. If you want to generate a debug build, use the command-> cmake -DBUILD_DEBUG=ON.   6. Once your build completes you will find the build products in the cmake directory. From here, open the project in your IDE of choice. NOTE: You should receive messages confirming successful binding, authentication, and connection after the main.c file edits have been made.       Step 3: Run Sample Code   The C code in the sample download is configured to run and connect to the Entities provided in the ThingWorxEntitiesExport.xml file. Make note of the IP address of your ThingWorx Composer instance. The top level of the exported zip file will be referred to as [C SDK HOME DIR]. Navigate to the [C SDK HOME DIR]/examples/ExampleClient/src directory. Open the main.c source file.  Operating System      Command Linux/Ubuntu gedit main.c OR vi main.c Mac open –e main.c Windows start main.c   3. Modify the Server Details section at the top with the IP address for your ThingWorx Platform instance and the Application Key you would like to use. Change the TW_HOST definition accordingly. NOTE: By default, TW_APP_KEY has been set to the Application Key from the admin_key in the import step completed earlier. Using the Application Key for the default Administrator is not recommended. If administrative access is absolutely necessary, create a user and place the user as a member of the Admins security group. /* Server Details */ #define TW_HOST "127.0.0.1" #define TW_APP_KEY "ce22e9e4-2834-419c-9656-e98f9f844c784c"   4. If you are working on a port other than 80, you will need to update the conditional statement within the main.c source file. Search for and edit the first line within the main function. Based on your settings, set the int16_t port to the ThingWorx platform port. 5. Click Save and close the file. 6. Create a directory to build in, for this example call it bin.  Operating System            Command Linux/Ubuntu mkdir bin Mac mkdir bin Windows mkdir bin   7. Change to the newly created bin directory.  Operating System              Command Linux/Ubuntu cd bin Mac cd bin Windows cd bin   8. Run the CMake command using your specific IDE of choice. NOTE: Include the two periods at the end of the code as shown below. Use cmake -G to see a list of supported IDEs. cmake ..   9. Once your build completes, you will find the build products in the bin directory, and you can open the project in your IDE of choice. NOTE: You should receive messages confirming successful binding, authentication, and connection after building and running the application. 10. You should be able to see a Thing in your ThingWorx Composer called SimpleThing_1 with updated lastConnection and isConnected properties. SimpleThing_1 is bound for the duration of the application run time.   The below instructions will help to verify the connection.   Click Monitoring. Click Remote Things from the list to see the connection status. You will now be able to see and select the Entity within the list.       Step 4: ExampleClient Connection   The C code provided in the main.c source file is preconfigured to initialize the ThingWorx C Edge SDK API with a connection to the ThingWorx platform and register handlers. In order to set up the connection, a number of parameters must be defined. This can be seen in the code below.   #define TW_HOST "127.0.0.1" #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c #if defined NO_TLS #define TW_PORT = 80; #else #define TW_PORT = 443; #endif   The first step of connecting to the platform: Establish Physical Websocket, we call the twApi_Initialize function with the information needed to point to the websocket of the ThingWorx Composer. This function:   Registers messaging handlers Allocates space for the API structures Creates a secure websocket err = twApi_Initialize(hostname, port, TW_URI, appKey, NULL, MESSAGE_CHUNK_SIZE, MESSAGE_CHUNK_SIZE, TRUE); if (TW_OK != err) { TW_LOG(TW_ERROR, "Error initializing the API"); exit(err); }   If you are not using SSL/TLS, use the following line to test against a server with a self-signed certificate: twApi_SetSelfSignedOk();   In order to disable HTTPS support and use HTTP only, call the twApi_DisableEncryption function. This is needed when using ports such as 80 or 8080. A call can be seen below:   twApi_DisableEncryption();   The following event handlers are all optional. The twApi_RegisterBindEventCallback function registers a function that will be called on the event of a Thing being bound or unbound to the ThingWorx platform. The twApi_RegisterOnAuthenticatedCallback function registered a function that will be called on the event the SDK has been authenticated by the ThingWorx Platform. The twApi_RegisterSynchronizeStateEventCallback function registers a function that will be called after binding and used to notify your application about fields that have been bound to the Thingworx Platform.   twApi_RegisterOnAuthenticatedCallback(authEventHandler, TW_NO_USER_DATA); twApi_RegisterBindEventCallback(NULL, bindEventHandler, TW_NO_USER_DATA); twApi_RegisterSynchronizeStateEventCallback(NULL, synchronizeStateHandler, TW_NO_USER_DATA);   NOTE: Binding a Thing within the ThingWorx platform is not mandatory, but there are a number of advantages, including updating Properties while offline.    You can then start the client, which will establish the AlwaysOn protocol with the ThingWorx Composer. This protocol provides bi-directional communication between the ThingWorx Composer and the running client application. To start this connection, use the line below:   err = twApi_Connect(CONNECT_TIMEOUT, RETRY_COUNT); if(TW_OK != err){ exit(-1); }   Click here to view Part 2 of this guide.      
View full tip
    Use ThingWorx Kepware Server as an OPC UA Client   GUIDE CONCEPT   This guide will explain how ThingWorx Kepware server can function as both an OPC UA Server, and a client to a remote OPC UA Server.   Following the steps in this guide, you will create a OPC UA server in Azure, then we will teach you how to use data from the OPC UA server in ThingWorx.       YOU'LL LEARN HOW TO   Create an OPC UA Server in Azure Configure Kepware as on OPC UA Client Connect Kepware to ThingWorx Foundation Monitor OPC UA data in ThingWorx Composer   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 60 minutes     Step 1: Overview Diagram   In this guide, ThingWorx Kepware Server will serve as both an OPC UA client, and a ThingWorx Foundation client. ThingWorx Kepware Server is able to connect through firewalls to provide a seamless, end-to-end connection from an OPC UA server to ThingWorx Composer. Two ThingWorx Kepware Server instances can be configured to provide a tunnel for transporting machine data across the internet.       This guide will show how to create an OPC UA server in Azure, then browse the server data using Kepware. We will create a ThingWorx Thing with a Property that dynamically represents the value on the remote server.     Step 2: Install ThingWorx Kepware Server   In addition to OPC UA, ThingWorx Kepware Server includes over 150 factory-automation protocols. ThingWorx Kepware Server communicates between industrial assets and ThingWorx Foundation, providing streamlined, real-time access to OT and IT data — whether that data is sourced from on-premise web servers, off-premise cloud applications, or at the edge. This step will download and install ThingWorx Kepware Server. Download the ThingWorx Kepware Server executable installer. Right-click on the installer and select Run as administrator. Click Yes in the pop-up asking if you want to proceed. Select your Language and click OK.     On the "Welcome" screen, click Next.     Accept the End-User License Agreement and click Next.     Set the destination folder for the installation and click Next.     Set the Application Data Folder location and click Next. Note that it is recommended NOT to change this path.     Select whether or not you'd like a Shortcut to be created and click Next.     On the "Vertical Suite Selection" screen, keep the default of Typical and click Next.     On the "Select Features" screen, keep the defaults and click Next.     The "External Dependencies" screen simply lists everything that will be installed; click Next.     On the "Default Application Settings" screen, leave the default of Allow client applications to request data through Dynamic Tag address and click Next.     On the “User Manager Credentials” screen, set a unique strong password for the Administrator account and click Next. Note that skipping setting a password can leave your system less secure and is not recommended in a production environment.     Click Install to being the installation.     Click Finish to exit the installer.       Step 3: Create Industrial Gateway   To make a connection between ThingWorx Kepware Server and ThingWorx Foundation, you must first create a Thing.    In ThingWorx Composer, click Browse. On the left, click Modeling -> Things.     Click + NEW. In the Name field, enter IndConn_Server, including matching capitalization.     If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. In the Base Thing Template field, enter indus, then select the IndustrialGateway Thing template from the sorted list. Click Save.   Step 4: Connect Kepware to ThingWorx   This step will get ThingWorx Kepware Server set-up and connected to ThingWorx Foundation.   Now that you have created an Industrial Gateway Thing, you can configure ThingWorx Kepware Server to connect to ThingWorx Foundation.   Follow the steps to Create an Application Key and note the value. The appKey will be used in the the next step. Open the ThingWorx Kepware Server Configuration Windows application, then right-click on Project.     Select Properties….     In the Property Editor pop-up, click ThingWorx. In the Enable field, select Yes from the drop-down. In the Host field, enter the URL or IP address of your ThingWorx Foundation server, without http:// or https://. Enter the Port number.       In the Application Key field, copy and paste the Application Key you just created. In the Trust self-signed certificates field, select Yes from the drop-down. In the Trust all certificates field, select Yes from the drop-down. In the Disable encryption field, select No from the drop-down if you are using another server that uses TLS - URL begins with https://. Select Yes if you are using a ThingWorx Foundation server without TLS - URL begins with http:// Type IndConn_Server in the Thing Name field, including matching capitalization. If you are connecting with a remote instance of ThingWorx Foundation and you expect any breaks or latency in your connection, enable Store and Forward. Click Apply in the pop-up. Click Ok.   In the ThingWorx Kepware Server Event window at the bottom, you should see a message indicating Connected to ThingWorx.     NOTE: If you do not see the “Connected” message, repeat the steps above, ensuring that all information is correct. In particular, check the Host, Port, and Thing name fields for errors.     Step 5: Connect OPC UA Server to Kepware   Now that you have created an Industrial Gateway Thing, and ThingWorx Kepware Server is connected to ThingWorx Foundation, we can connect an OPC UA server to Kepware   Follow the steps to create an OPC UA server in Azure. Enter Resource Group, click Review + create.     Click Create.     In about a minute, the deployment success screen will be displayed.     Click Go to resource, and copy FQDN.     Open ThingWorx Kepware Server Configuration.     Right-click, then click New Channel. Scroll down to select OPC UA Client, then click Next.     Click Next twice to accept default settings, then enter the FQDN copied earlier. Add :50000 to the end of the domain name.     Click Next to accept all defaults. Click Yes to trust the certificate.   Click here to view Part 2 of this guide.
View full tip
    Send data from an MXChip Developer kit to your Azure IoT Hub   GUIDE CONCEPT   Users of the MXChip IoT DevKit (a.k.a. MXChip), follow these quick steps to send temperature and humidity data from built-in IoT DevKit sensors to the Azure IoT Hub.   YOU'LL LEARN HOW TO   Connect the IoT DevKit to a wireless access point Create an Azure IoT Hub and register a device for the IoT DevKit Connect IoT Devkit to Azure IoT Hub   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 80 minutes   Step 1: Create an Azure IoT Hub   Choose +Create a resource, then choose Internet of Things. Click Iot Hub from the list on the right. You see the first screen for creating an IoT hub.   Fill in the fields.   Subscription: Select the subscription to use for your IoT hub.   Resource Group: You can create a new resource group or use an existing one. To create a new one, click Create new and fill in the name you want to use. To use an existing resource group, click Use existing and select the resource group from the dropdown list.   Region: This is the region in which you want your hub to be located. Select the location closest to you from the dropdown list.   IoT Hub Name: Put in the name for your IoT Hub. This name must be globally unique. If the name you enter is available, a green check mark appears.         3. Click Next: Size and scale to continue creating your IoT hub.     On this screen, you can take the defaults and just click Review + create at the bottom.   Pricing and scale tier: You can choose from several tiers depending on how many features you want and how many messages you send through your solution per day. The free tier is intended for testing and evaluation. It allows 500 devices to be connected to the IoT hub and up to 8,000 messages per day. Each Azure subscription can create one IoT Hub in the free tier.   IoT Hub units: The number of messages allowed per unit per day depends on your hub’s pricing tier. For example, if you want the IoT hub to support ingress of 700,000 messages, you choose two S1 tier units.   Advanced / Device-to-cloud partitions: This property relates the device-to-cloud messages to the number of simultaneous readers of the messages. Most IoT hubs only need four partitions.               4. Click Review + create to review your choices. You see something similar to this screen.           5. Click Create to create your new IoT hub. Creating the hub takes a few minutes.     Step 2: Create IoT device   Navigate to the IoT Hub created and in the IoT Devices page, click + New.   2. Enter the device ID used by the demo MXChip application MyNodeDevice. Use the default settings for auto-generating authentication keys and connecting the new device to your hub. Click Save.   3. Navigate to the device created and make a note of the device connection string, which looks like: HostName={YourIoTHubName}.azure-devices.net;DeviceId=MyNodeDevice;SharedAccessKey={YourSharedAccessKey}.   Create Azure Storage   The ThingWorx Azure IoT Connector we will install in the next guide requires an Azure Storage Account. Follow the Microsoft documentation to create an Azure Storage account. NOTE: Select Blob storage as the account type and the Hot Access Tier.     Step 3: Connect to Azure IoT Hub   Download the latest version of GetStarted firmware for IoT DevKit. Connect IoT DevKit to your computer via USB. In Windows you see a new USB mass storage device in Windows Explorer called AZ3166. Drag and drop the .bin file you downloaded from step 1 into the disk named AZ3166 and wait for IoT Devkit to restart. Internet connectivity is required to connect to Azure IoT Hub. Use AP Mode on the DevKit to configure and connect to Wi-Fi.Hold down button B, push and release the Reset button, and then release button B. Your IoT DevKit enters AP mode for configuring the Wi-Fi connection. The screen displays the service set identifier (SSID) of the DevKit and the configuration portal IP address:     5. Use a Web browser on a different Wi-Fi enabled device (computer or mobile phone) to connect to the IoT DevKit SSID displayed in the previous step. If it asks for a password, leave it empty.     6. Open 192.168.0.1 in the browser. Select or input the Wi-Fi network that you want the IoT DevKit to connect to, type the password for the Wi-Fi conection and input the device connection string you made notge of in step 1. Then click Connect.     7. The WiFi credentials and device connection string will be saved in the IoT DevKit even after power cycliong. The following page will be displayed in the browser:     8. The IoT DevKit reboots in a few seconds. You then see the assigned Wi-Fi IP address on the screen of the IoT DevKit:     9. Wait for the IoT DevKit to connect to Azure IoT Hub and you will see it sending telemetry data including temperature and humidity value to Azure IoT Hub. The screen of the IoT Devkit would show message count and temperature/humidity data.       Step 4: Next Steps   Congratulations! You've successfully completed the Connect MXChip to Azure IoT guide. By following the steps in this lesson, you created an Azure IoT Hub and device.     The next guide in the Azure MXChip Development Kit learning path is Create an Application Key.   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Analyze Build a Predictive Analytics Model Build Get Started with ThingWorx for IoT   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Azure Support Page    
View full tip
  Connect an ESP8266 WiFi module using the Arduino programming environment and the ThingWorx REST API.   This information was created for a previous version of ThingWorx and may not be fully accurate. Report any issues with this article here.   Guide Concept   This project will introduce the utilities ThingWorx provides for connections to an Adafruit Feather.   Following the steps in this guide, you will have a fully configured setup between your Adafruit Feather and the ThingWorx platform to begin your IoT development.   We will teach you how to utilize the ThingWorx REST API and the Arduino programming language to connect your Adafruit Feather for IoT application development.   You'll learn how to   Connect an ESP8266 WiFi module to a ThingWorx server Use the Arduino programming environment with the ThingWorx REST API   NOTE:  The estimated time to complete this guide is 30 minutes.      Step 1: Install Software   Arduino   There are three pieces of software to install before getting started with the ThingWorx-specfic code: Install FTDI USB driver. If you have connected development boards to your PC in the past you probably already have this installed. The latest Arduino IDE full install will also install the driver. NOTE: SparkFun has an excellent FTDI Driver Installation guide.   3. Arduino IDE - version 1.6.4 or later recommended. 4. Install ESP8266 addon into Arduino IDE. 5. The SparkFun Setting Up the Arduino IDE Tutorial is a great guide to getting started with their board. 6. Adafruit also has a great with their board Testing a Wifi Connection Tutorial.   When everything is set-up correctly and you are able to upload and see the Blink demo flashing the LED on the board you are ready to move to the next step.   ThingWorx Foundation Server   Start, and Launch your ThingWorx Foundation server. Log into Composer.  You will need a ThingWorx appKey to authorize the board.  Follow these instructions in Create an Application Key to create an appKey that you will copy into the source code in the next step.       Step 2: Set up Arduino IDE, Developer Board, and ThingWorx Server   Once you are able to run the blink test sketch, your IDE and board are set-up correctly. To learn how to run the blink test, read the SparkFun Board Instructions and the Adafruit board instructions.   Arduino IDE   Before you will be able to run the code below that connects a developement board to a ThingWorx Foundation server, you will need to modify the code with four pieces of information specific to your environment. You will need:   A WiFi access point SSID The correct password for the WiFi access point The IP address or URL of a ThingWorx Foundation Server A valid appKey created by your ThingWorx Foundation Server. To create an appKey, follow these instructions to Create An Application Key   Create a new sketch in the Arduino IDE then copy and paste the code below into the IDE.   Modify the WiFi Definitions and the ThingWorx server definitions shown in the code with your specficic information then save the sketch with a new name. The next step will describe what you should see when you upload and run the code on your developer board.   /** * * ESP8266_ThingWorx_REST_Demo.ino * * * (c) PTC, Inc. 2016-2020 * */ #include <Arduino.h> #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #include <WiFiClientSecureBearSSL.h> ////////////////////// // WiFi Definitions // ////////////////////// const char WiFiSSID[] = "Liberty454"; // WiFi access point SSID const char WiFiPSK[] = "Flutie22"; // WiFi password - empty string for open access points ////////////////////////////////////////////// // ThingWorx server definitions // // modify for a specific platform instance // ////////////////////////////////////////////// const char TWPlatformBaseURL[] = "https://pp-2007011431nt.devportal.ptc.io"; const char appKey[] = "2d4e9440-3e51-452f-a057-b55d45289264"; //////////////////////////////////////////////////////// // Pin Definitions - board specific for Adafruit board// //////////////////////////////////////////////////////// const int RED_LED = 0; // Thing's onboard, red LED - const int BLUE_LED = 2; // Thing's onboard, blue LED const int ANALOG_PIN = A0; // The only analog pin on the Thing const int OFF = HIGH; const int ON = LOW; // this will set as the Accept header for all the HTTP requests to the ThingWorx server // valid values are: application/json, text/xml, text/csv, text/html (default) #define ACCEPT_TYPE "text/csv" ///////////////////// //Attempt to make a WiFi connection. Checks if connection has been made once per second until timeout is reached //returns TRUE if successful or FALSE if timed out ///////////////////// boolean connectToWiFi(int timeout){ Serial.println("Connecting to: " + String(WiFiSSID)); WiFi.begin(WiFiSSID, WiFiPSK); // loop while WiFi is not connected waiting one second between checks uint8_t tries = 0; // counter for how many times we have checked while ((WiFi.status() != WL_CONNECTED) && (tries < timeout) ){ // stop checking if connection has been made OR we have timed out tries++; Serial.printf(".");// print . for progress bar Serial.println(WiFi.status()); delay(2000); } Serial.println("*"); //visual indication that board is connected or timeout if (WiFi.status() == WL_CONNECTED){ //check that WiFi is connected, print status and device IP address before returning Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); return true; } else { //if WiFi is not connected we must have exceeded WiFi connection timeout return false; } } ////////////////////////// //create a name for the board that is probably unique by appending last two bytes of MAC address //return name as a String /////////////////////////////// String getUniqueDeviceName(){ String uniqueName; uint8_t mac[WL_MAC_ADDR_LENGTH]; WiFi.macAddress(mac); // WiFi does NOT need to be connected for this call String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) + String(mac[WL_MAC_ADDR_LENGTH - 1], HEX); macID.toUpperCase(); uniqueName = "ESP8266Board-" + macID; Serial.println("DeviceID>" + uniqueName); return uniqueName; } /////////////////////////////// // make HTTP GET to a specific Thing and Propertry on a ThingWorx server // thingName - Name of Thing on server to make GET from // property - Property of thingName to make GET from // returns HTTP response code from server and prints full response /////////////////////////////// int httpGetPropertry(String thingName, String property){ std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure); client->setInsecure(); HTTPClient https; int httpCode = -1; String response = ""; Serial.print("[httpsGetPropertry] begin..."); String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Things/"+ thingName +"/Properties/"+ property +"?appKey=" + String(appKey); https.begin(*client,fullRequestURL); https.addHeader("Accept",ACCEPT_TYPE,false,false); Serial.println("GET URL>" + fullRequestURL +"<"); // start connection and send HTTP header httpCode = https.GET(); // httpCode will be negative on error if(httpCode > 0) { response = https.getString(); Serial.printf("[httpGetPropertry] response code:%d body>",httpCode); Serial.println(response + "<\n"); } else { Serial.printf("[httpGetPropertry] failed, error: %s\n\n", https.errorToString(httpCode).c_str()); } https.end(); return httpCode; } /////////////////////////////// // makes HTTP POST to platform to CreateThing service using input string as the new Things's name. // Returns server response code /////////////////////////////// int createThing(String nameOfThing){ std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure); client->setInsecure(); HTTPClient https; int httpCode = -1; String response = ""; Serial.print("[createThing] begin..."); String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Resources/EntityServices/Services/CreateThing?appKey=" + String(appKey); https.begin(*client,fullRequestURL); https.addHeader("Accept",ACCEPT_TYPE,false,false); https.addHeader("Content-Type","application/json",false,false); Serial.println("POST URL>" + fullRequestURL + "<"); // start connection and send HTTP header httpCode = https.POST("{\"name\": \""+ nameOfThing +"\",\"thingTemplateName\": \"GenericThing\"}"); // httpCode will be negative on error if(httpCode > 0) { response = https.getString(); Serial.printf("[createThing] response code:%d body>",httpCode); Serial.println(response + "<\n"); } else { Serial.printf("[createThing] POST... failed, error: %s\n\n", https.errorToString(httpCode).c_str()); } https.end(); return httpCode; } /////////////////////////////// // make HTTP POST to ThingWorx server Thing service // nameOfThing - Name of Thing to POST to // endPoint - Services URL to invoke // postBody - Body of POST to send to ThingWorx platform // returns HTTP response code from server /////////////////////////////// int postToThing(String nameOfThing, String endPoint, String postBody){ std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure); client->setInsecure(); HTTPClient https; int httpCode = -1; String response = ""; Serial.print("[postToThing] begin..."); String fullRequestURL = String(TWPlatformBaseURL) + "/Thingworx/Things/"+ nameOfThing +"/Services/"+ endPoint +"?appKey=" + String(appKey); Serial.println("URL>" + fullRequestURL + "<"); https.begin(*client,fullRequestURL); https.addHeader("Accept",ACCEPT_TYPE,false,false); https.addHeader("Content-Type","application/json",false,false); Serial.println("[postToThing] POST body>" + postBody + "<"); // start connection and send HTTP header httpCode = https.POST(postBody); // httpCode will be negative on error if(httpCode > 0) { response = https.getString(); Serial.printf("[postToThing] response code:%d body>",httpCode); Serial.println(response + "<\n"); } else { Serial.printf("[postToThing] POST... failed, error: %s\n\n", https.errorToString(httpCode).c_str()); } https.end(); return httpCode; } void setup() { pinMode(RED_LED, OUTPUT); pinMode(BLUE_LED, OUTPUT); Serial.begin(115200); Serial.setDebugOutput(true); Serial.println(); Serial.println(); Serial.println(); Serial.printf("Starting...\n"); for(uint8_t t = 4; t > 0; t--) { Serial.printf(" WAIT %d...\n", t); Serial.flush(); delay(1000); } connectToWiFi(10); } void loop() { String thingName = getUniqueDeviceName(); //unique name for this Thing so many work on one ThingWorx server while (WiFi.status() == WL_CONNECTED) { //confirm WiFi is connected before looping as long as WiFi is connected int getResponseCode = httpGetPropertry(thingName, "SomeNumber"); if (getResponseCode == 404){ // a 404 means connected, but either no Thing or no property // first we will try to create a new Thing on the platform int postResp = createThing(thingName); // saving the response code for retry logic in the future // the newly crated Thing has to be enabled postResp = postToThing(thingName,"EnableThing",""); //POST to EnableThing endpoint with no body // after the new Thing is enabled it must be restarted postResp = postToThing(thingName,"RestartThing",""); //POST to RestartThing endpoint with no body // add a property to the Thing 3rd parameter is ugly because required quotes are escaped with backslashes postResp = postToThing(thingName,"AddPropertyDefinition", "{\"name\":\"SomeNumber\",\"type\":\"NUMBER\"}"); //POST body contains JSON object with property name and property type // after changes to a Thing's structure it must be restarted postResp = postToThing(thingName,"RestartThing",""); //POST to RestartThing endpoint with no body } delay(2000); }// end WiFi connected while loop Serial.printf("****Wifi connection dropped****\n"); WiFi.disconnect(true); delay(10000); connectToWiFi(10); }     Step 3: Run Arduino Demo   Click on the right arrow in the Arduino IDE toolbar to upload and start the sketch. Note:The compile and upload process will take almost a minute and will show [ 100% ] when it is completed successfully. 2. After the upload is complete, click on Tools > Serial Monitor and select 115200 baud from the drop down in the lower right.            Check Connection on ThingWorx Server   Open the Composer window of your ThingWorx Foundation server and click on the browse folder icon, then Things.   You will see a Thing named "ESP8266Board-XXXX" with XXXX replaced by the last 4 digits of your boards WiFi MAC address. Click on the Thing then click the Properties and Alerts tab in the left column. Click the pencil "Set value" icon in the value column and enter a number in the text box. Click the "Check" button to set the value.   Open the Arduino Serial monitor window, and you will see the value you just entered on the platform shown in the serial output.   Step 4: Next Steps   Congratulations! You've successfully completed the Connect an Arduino Developer Board Quickstart.   This guide has given you the basic tools to:   Set up Arduino IDE Run Arduino demo Check connection on ThingWorx Server   Learn More   We recommend the following resources to continue your learning experience:    Capability Guide Connect Use REST API to Access ThingWorx Build Data Model Introduction   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource Link Community Developer Community Forum Support REST API Help Center
View full tip
  Step 7: Import Extension   In the ThingWorx Composer. in the bottom left, click Import/Export, then select Import.   NOTE: The build produces a zip file in AuthenticatorExample->build->distributions folder. This zip file will be required for importing the extension.          2. For the Import Option field, select Extension.            3. Click Browse and choose the zip file in the distributions folder (located in the Eclipse Project's build directory).       4. Click Import to finalize the import.   Navigate to New Authenticator   Navigate to and select Security > Authenticators.            2. You will now see your CustomizedAuthenticator Authenticator as a option to view/edit.            3. Click Edit or View to see this new Authenticator. You wil notice the priority is 1.   Troubleshooting   If your import did not get through with the two green checks, you may want to modify your metadata.xml or java code to fix it depending on the error shown in the logs.     Issue Solution JAR Conflict arises between two similar jars JAR conflicts arise when a similar jar is already present in the Composer database. Try to remove the respective jar resources from the metadata.xml. Add these jars explicitly in twx-lib folder in the project folder inside the workspace directory. Now, build the project and import the extension in ThingWorx Composer once again. JAR is missing Add the respective jar resource in metadata.xml using the ThingWorx->New Jar Resource. Now, build the project and import the extension in ThingWorx Composer once again. Minimum Thingworx Version [ 7.2.1] requirements are not met because current version is: 7.1.3 The version of SDK you have used to build your extension is higher than the version of the ThingWorx Composer you are testing against. You can manually edit the configfiles->metadata.xml file to change the Minimum ThingWorx version to your ThingWorx Composer version.     Step 8: Integrating Custom Authentication   Integration can be handled in different methods based on your security needs and architecture. The Authenticator we created works with the demo site we provided in the download.   Create ThingWorx User   Let's create the User that we will be processing login attempts.   In the ThingWorx Composer, click the + at the top left of the screen.   Select User in the dropdown.   Set the Project (ie, PTCDefaultProject) and enter the Name for this new user as TwxUser. Enter the Password for the new user to something easy to remember (ie, 2020Password2021).   Click Save.   Create Logger   Create a helpful logger for authentication attempts.   Create a Thing named AuthenticationStamper to go with the LoginHelper variable in the earlier Java source code. Ensure this new Thing inherits from the RemoteThing Match the properties for the AuthenticationStamper with the two properties in the below image.   Save the changes.   Create Login Helper   Create a stream for authentication attempts for helpful tracking. Create a ValueStream named AuthenticationStream and Save the Entity. In the Properties and Alerts section of the ValueStream, click Manage Bindings.   Setup the binding to match the below configurations. Bind the properties to the AuthenticationStamper Thing.   Save the changes made to the ValueStream.   Demo Page Login   With a browser, open the TestSite.html web page found in the Demo directory of the download. You should see a login page similar to that as the below image.   Enter the name of the user we created, TwxUser. Enter the password for the user. We suggested setting this to Password2019. Click Submit. You will now be authenticated and logged in.     Step 9: Next Steps   Congratulations! You've successfully completed the Create An Authentication Extension tutorial, and learned how to:   Install the Eclipse Plugin and Extension SDK Create and configure an Extension project Create Authentication Application Build and import an Extension   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Application Development Tips & Tricks   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Extension Development Guide    
View full tip
  Guidelines for selecting the optimal method for connecting to ThingWorx   GUIDE CONCEPT   In the world of IoT application development, connectivity refers to the infrastructure and protocols which connect devices to the cloud or network. Edge devices handle the interface between the physical world and the cloud.   ThingWorx provides you with several different tools for connecting to the Thingworx platform.   This guide is designed as an introduction to these tools, and will help you determine which to choose based on your specific requirements.   YOU'LL LEARN HOW TO   Pros and cons of different connection methods The connection method best suited for some typical applications Where to find detailed information about any connection method   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes   Step 1: Connectivity Method Options   There are many factors that will influence your decision about the ideal mechanism to connect to ThingWorx. On this page we compare and contrast different methods and give examples for where each one is a natural fit.   Connectivity Method Developer Benefit REST API Integrate seamlessly using dynamically-generated API calls Azure IoT Hub Connector Connect devices that use Azure IoT Hub Edge SDKs Build full-featured integrations for any platform ThingWorx Kepware Server Connect out-of-the-box with over 150 protocol drivers for industrial equipment Edge MicroServer Establish bi-directional connectivity with this complete, ready-to-run agent   REST API   Pros Cons Typical use case Skills Required Connection Type  Web developer can easily create integration ThingWorx cannot trigger action on the edge Push data from small devices to ThingWorx REST API development Request/Response   Using the ThingWorx REST API is an easy way for low-capability devices to connect with a ThingWorx platform. Any edge device that can make an HTTP POST can read and update properties or execute services on a ThingWorx platform. The disadvantage of this method is that it is one way from edge to platform. There is no way for the platform to initiate a service on the remote device and properties are only updated when the edge device initiates a connection with ThingWorx.   Learn more about the ThingWorx REST API:   Use REST API to Access ThingWorx Using the Connect an Arduino Developer Board tutorial REST API Documentation   Azure IoT Hub Connector   Pros Cons Typical use Case Skills Required Connection Type  Easily connect devices that use Azure IoT Hub Adds dependency and cost to application Add ThingWorx for devices connected with the Azure cloud Azure edge development AlwaysOn™   The diagram illustrates device-to-cloud integration with the Azure IoT Hub.   The ThingWorx Azure IoT Hub Connector establishes network connections to both ThingWorx Foundation and the Azure IoT Hub. Data flows in from devices, through the Azure IoT Hub hosted in the cloud, to the ThingWorx Azure IoT Hub Connector configured for a specific ThingWorx instance. The ThingWorx Azure IoT Hub Connector translates messages from the Azure IoT Hub format, to the native ThingWorx format and uses an established AlwaysOn connection to forward the information to ThingWorx Foundation.   Azure IoT Hub   Connect Azure IoT Devices   Edge SDKs   Pros Cons Typical Use case Skill Required Connection Type  Fully integrate device or remote system with ThingWorx platform Most developer flexibility All functionality must be developed by programmer Full customization or tight integration required Application development in Java, C, or .Net AlwaysOn™   These SDKs are developer tools that wrap the protocol used to connect to the ThingWorx Platform. There are SDK's available for Java, C, and .Net languages. The Edge MicroServer uses the C SDK internally. All SDKs use the ThingWorx AlwaysOn binary protocol together with the HTTP WebSocket protocol for transport. WebSocket connections can operate through a firewall allowing two-way, low latency communication between the device and server. The SDKs support the following key concepts that allow a Thing developed with an SDK to be a full-fledged entity in the ThingWorx environment:   Remote properties — Entities that define the types, identities, and values from a device or remote system Services — Actions that can be performed on demand by a device or remote system Events — Data that is sent to a subscribed device or remote system whenever the Event is triggered   You can choose from any of the SDK's to create a custom application that meets their exact requirements.   C SDK   The C SDK is the most lightweight of all the SDKs and will result in an application that uses the least amount of RAM, frequently requiring less than 200kB. It is the only SDK that is distributed as source code, allowing compilation of C SDK applications on any platform even those without an operating system.   Learn more about the C SDK:   C SDK Tutorial C SDK Documentation   Java SDK   The Java SDK is designed for portability and simplicity to ease connecting any Java-enabled device or system to ThingWorx. The Java SDK is provided as .jar files and sample Java source code. Any system that can run Java 1.7.51 or later should be able to build and run the example applications.   Learn more about the Java SDK:   Java SDK Tutorial Java SDK Documentation   .Net SDK   The .Net SDK is provided as .dll files with sample Visual C# project files and source code. Any system that can run Microsoft NET 3.5 SP1 Framework development environment should be able to build and run the example applications.   Learn more about the .Net SDK:   .Net SDK Documentation   ThingWorx Kepware Server   Pros Cons Typical Use case Skill Required Connection Type  Easily connect to hundreds of different types of industrial equipment Requires computer running Windows physically connected to device Adding ThingWorx to an industrial setting Configure settings AlwaysOn™   The ThingWorx Kepware Server Windows client lets users quickly and easily connect real-time, bi-directional industrial controls data to the ThingWorx IoT Platform via the ThingWorx AlwaysOn protocol. ThingWorx services enable users to browse, read, write, and interact with ThingWorx Kepware Server, and includes intuitive tools that simplify the modeling of industrial things.   Learn more about the ThingWorx Kepware Server:   Connect Industrial Devices and Systems ThingWorx Kepware Server Documentation ThingWorx Kepware Server Manual   Edge MicroServer   Pros Cons Typical Use case Skill Required Connection Type  Easily connect with simple scripting Requires a device running Windows or Linux Customization with Lua scripting Connecting gateway router to ThingWorx Configure settings AlwaysOn™   The ThingWorx Edge MicroServer is a binary executable available for Windows and Linux running on either ARM or x86 processors. The EMS establishes an AlwaysOn, bi-directional connection to a destination ThingWorx platform when it is started. The EMS is configured by editing a json text file to specify the target platform and credentials. The EMS uses the always on connection to provide a local HTTP server that is a reflection of the platform REST API. This local copy of the platform API allows devices that are not capable of making encrypted connections across the open internet to securely interact with the platform. The EMS package also includes the Lua Script Resource application. This application extends the ThingWorx Foundation server by connecting through the EMS HTTP server and provides a Lua interpreter that can be used to connect local resources to the ThingWorx server.   Learn more about the ThingWorx Edge MicroServer:   Connect a Raspberry Pi to ThingWorx using the Edge MicroServer Edge MicroServer Documentation   Step 2: Next Steps   Congratulations! You've successfully completed the Choose a Connectivity Method guide.   At this point, you can make an educated decision regarding which connection methods are best suited for your application and infrastructure.   The next guide in the Connect and Configure Industrial Devices and Systems learning path is Use REST API to Access ThingWorx   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Connect ThingWorx Application Development Reference Build Get Started with ThingWorx for IoT 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 ThingWorx Connectors Help Center
View full tip
    Step 12: Connect to Temperature Sensor   This step is optional. Additional instructions are provided for developers who are interested in interfacing with sensors.   The DHT11 and DHT22 digital temperature and humidity sensors are inexpensive and available from several sources: Adafruit Sparkfun SeeedStudio The Raspberry Pi does not come with any built-in analog to digital conversion capability and because these sensors are digital they can be interfaced easily with a Raspberry Pi. We will be using a Python library developed by Adafruit that simplifies interfacing with these sensors.   Install Adafruit Python Library for Sensors   We will use Git to download the Adafruit DHT11 Python from GitHub. Check if Git is already installed by opening a command window and typing the command: git If you see a "command not found" error message use this command to install Git: sudo apt-get install git-core If you get an error installing Git, run the command: sudo apt-get update then try to install Git again. Change into the EMS directory: cd microserver Download the Adafruit library with this command: git clone https://github.com/adafruit/Adafruit_Python_DHT.git Change into the directory that was just downloaded: cd Adafruit_Python_DHT Install Python build libraries: sudo apt-get install build-essential python-dev Build and install the library with this command: sudo python setup.py install   Connect Sensor to Raspberry Pi Power down the Raspberry Pi before making any wire connections. To prevent any flash memory corruption, enter the command shutdown -h now then wait a few seconds for it to complete before disconnecting the power supply. Use female-to-female jumper wires to connect the sensor as shown below. The black wire is connected to ground, the red wire is 5v or VCC, and the yellow wire carries is the digital signal. WARNING: Double check your connections before applying power. Mistakes can destroy the sensor and the Raspberry Pi!   3. Apply power and boot the Raspberry Pi. 4. Change into the EMS directory:   cd microserver 5. Test the sensor with this commmand:   ./Adafruit_Python_DHT/examples/AdafruitDHT.py 11 4   In a few a seconds the current temperature and humidity will be displayed. Change the 11 parameter to 22 if you are using the DHT22 sensor. The 4 parameter is the GPIO pin number of the Raspberry Pi that is conneCted to the sensor's signal pin. This command is the same command the luaScriptResource will use to get temperature and humidity readings.   Modify Lua template file A dozen lines need to be added to the file PiTemplate.lua file in the /microserver/etc/custom/templates directory.   After the line: properties.cpu_volt = { baseType="NUMBER", pushType="ALWAYS", value=0 } Add the two lines: properties.temp = { baseType="NUMBER", pushType="ALWAYS", value=0 } properties.humidity = { baseType="NUMBER", pushType="ALWAYS", value=0 } After the line: local voltCmd = io.popen("vcgencmd measure_volts core") Add the line: local sensorCmd = io.popen("./Adafruit_Python_DHT/examples/AdafruitDHT.py 11 4") After the line: properties.cpu_volt.value = s Add these 9 lines: -- set property temp and humidity local sensor = sensorCmd:read("*a") log.debug("[PiTemplate]",string.format("raw sensor %s", sensor)) s = string.match(sensor,"Temp=(%d+\.%d+)"); log.debug("[PiTemplate]",string.format("scaled temp %.1f", s)) properties.temp.value = s s = string.match(sensor,"Humidity=(%d+\.%d+)"); log.debug("[PiTemplate]",string.format("scaled humidity %.1f", s)) properties.humidity.value = s Stop and then restart luaScriptResource by using the following commands. ps -efl Will list all running processes, note the number in the PID column for ./lusScriptResource kill -9 PID# Replace PID# with number noted above and the process will be ended. Run LuaScriptResource by executing the following command: sudo ./luaScriptResource   Update Properties of PiThing   Log onto ThingWorx Foundation server. Click on the Home icon in Composer then broswse to Things > PiThing > Properties and click Manage Bindings button.   Click on the Remote tab, then drag and drop the temp and humidity Properties one at a time to the green plus sign next to Create new Properties. Click Done to close the binding window, then click Save. NOTE: The temp and humidity Properties will be updated every 30 seconds.     Step 13: Next Steps   Congratulations! You've successfully completed the Connect Raspberry Pi to ThingWorx guide, and learned how to:   Set up Raspberry Pi Install, configure and launch the EMS Connect a remote device to ThingWorx   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Manage Data Model Introduction Build Get Started with ThingWorx for IoT   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Edge SDKs and WebSocket-based Edge MicroServer (WS EMS) Help Center External Raspberry Pi Documentation  
View full tip
  Step 8: Configure Template File (Service)   Services are implemented as Lua functions. In our Lua script, Services are divided into two pieces. The first is the Service definition which consists of a Service name, inputs and output. The second part of defining a Service is the service code. The Service code is run when you execute the service.   Create Service Definition Open the PiTemplate.lua file. Append the service definition to the file. Create a service named GetSystemProperties that gets the system properties (cpu temperature, clock frequencies, voltages) from your Raspberry Pi and updates the respective properties on the Thingworx platform. Specify your output type but not the name because the name of every output from a ThingWorx service is always result. serviceDefinitions.GetSystemProperties( output { baseType="BOOLEAN", description="" }, description { "updates properties" } ) NOTE: This service has no input parameters and an output that results in True if the properties were successfully updated on Thingworx.   Create Service code The Service code is run when you execute the Service. Functions in Lua are variables therefore to define the Service code, you will create a variable. The name of the Service has to match the name you specified in the Service definition.   Copy the service code below with comments explaining the logic and add append it to your template file, or download and unzip the full PiTemplate.zip attached here. services.GetSystemProperties = function(me, headers, query, data) log.trace("[PiTemplate]","########### in GetSystemProperties#############") queryHardware() -- if properties are successfully updated, return HTTP 200 code with a true service return value return 200, true end function queryHardware() -- use the vcgencmd shell command to get raspberry pi system values and assign to variables -- measure_temp returns value in Celsius -- measure_clock arm returns value in Hertz -- measure_volts returns balue in Volts local tempCmd = io.popen("vcgencmd measure_temp") local freqCmd = io.popen("vcgencmd measure_clock arm") local voltCmd = io.popen("vcgencmd measure_volts core") -- set property temperature local s = tempCmd:read("*a") s = string.match(s,"temp=(%d+\.%d+)"); log.debug("[PiTemplate]",string.format("temp %.1f",s)) properties.cpu_temperature.value = s -- set property frequency s = freqCmd:read("*a") log.debug("[PiTemplate]",string.format("raw freq %s",s)) s = string.match(s,"frequency%(..%)=(%d+)"); s = s/1000000 log.debug("[PiTemplate]",string.format("scaled freq %d",s)) properties.cpu_freq.value = s -- set property volts s = voltCmd:read("*a") log.debug("[PiTemplate]",string.format("raw volts %s", s)) s = string.match(s,"volt=(%d+\.%d+)"); log.debug("[PiTemplate]",string.format("scaled volts %.1f", s)) properties.cpu_volt.value = s end tasks.refreshProperties = function(me) log.trace("[PiTemplate]","~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In tasks.refreshProperties~~~~~~~~~~~~~ ") queryHardware() end Save the PiTemplate.lua file. cntrl x     Step 9: Run LSR   1. Navigate from installation directory to microserver directory. cd microserver 2. Ensure that wsems is running in a separate terminal session before you start running LuaScriptResource. 3. Ensure that you have ownership to the executable luaScriptResource and executable privileges. To check ownership: Ls -la -rwxrwxr-x 1 pi pi 769058 Jun 9 17:46 luaScriptResourc NOTE: The owner of luaScriptResource should be the user you are logged in as on the Raspberry Pi.   4. Confirm you have executable privileges by running the following command: sudo chmod 775 luaScriptResource 5. Run LuaScriptResource by executing the following command: sudo ./luaScriptResource   6. The output will show an error until we create the corresponding Thing in the next step.     Step 10: Bind Remote Thing Properties   Now we need to register a Thing so your Raspberry Pi can bind to its Properties on the Thingworx Platform.   Create a Thing named PiThing that will bind the scripts.PiThing created in config.lua . Open your Composer screen. Click Things on the left-navigation and the + symbol. Enter PiThing in the Name field and click RemoteThing in the Thing Template field.   Click Save. Ensure that the Remote Thing Property is connected. Click Properties in the left-hand navigation. Verify that the isConnected Property has a value of true. This means that your Raspberry Pi is still connected and now bound to this Thing on Thingworx Platform.   Bind the remote Thing Properties. Make sure the Properties tab is selected and click Edit at the top of the PiThing. Click Manage Bindings. Select the Remote tab at the top.   Click Add All Above Properties or drag and drop the ones you need. Click Done. Click Save. Verify that the Properties were updated with readings from the Raspberry Pi. Both the Value and Default Value for the three Properties will be set to the current reading from the Raspberry Pi. Cover the Raspberry Pi and wait about a minute, then Select the Properties tab and click Refresh. You will see the cpu_temperature value change.     NOTE: The system properties from your Raspberry Pi are now being passed to the server every 30 seconds. Wait a couple of cycles to see if the values from the Raspberry Pi change. If you are impatient, manually change the value of the property using the Set button in the Composer then click Refresh to see the updated value. The value will be temporarily updated for about 30 seconds until the Raspberry Pi reports the current live value.   Troubleshooting Tips   Tip #1 If the properties are not updating, try to stop and start both the wsems and luaScriptResource services.   quit sudo ./wsems or ./luaScriptResource Tip #2 If a wsems and/or luaScriptResource is not shut down gracefully, sometimes the service is still running which can cause issues. You can search and kill any wsems/luaScriptResource services by using the following command. Re-run the GetSystemProperties to test if this fixed the issue.   ps -efl kill -9 <id#>   Step 11: View Data from Devices   In order to demonstrate how ThingWorx can render a visualization of data from connected devices, at this point in the lesson you will import a pre-configured Mashup.   On the ThingWorx server that the EMS is connected to, start on the Home tab of Composer. Import a pre-built Mashup. Download and save the pre-built Mashup XML file attached here: Mashups_PiThingMashup-v91.xml. In Composer, click the Import/Export drop-down at the bottom-left.   Click Import. Leave all default values and click Browse to select the Mashups_PiThingMashup-v91.xml file that you just downloaded. Click Open, then Import, and once you see the success message, click Close. View Mashup displaying live data. Select the home icon in the top left side of Composer, then click Mashups on the left-navigation panel. Click Mashups_PiThingMashup-v91 and you'll see the design view of the Mashup.   Click View Mashup, and you'll see the live Mashup.    TIP: You will need to allow pop-ups in your browser for the Mashup to be displayed.     Click here to view Part 4 of this guide. 
View full tip
  Step 4: Install and Configure   Before you install the plugin, ensure that software requirements are met for proper installation of the plugin.   Open The Eclipse IDE and choose a suitable directory as a workspace. Go to the menu bar of the Eclipse window and select Help->Install New Software… After the Install window opens, click Add to add the Eclipse Plugin repository. Click Archive… and browse to the directory where the Eclipse Plugin zip file is stored and click Open. NOTE: Do not extract this zip file. Enter a name (for example, Eclipse Plugin).   Click OK. Ensure that the Group items by category checkbox is not selected. Select ThingWorx Extension Builder in the items list of the Install window. Click Next and the items to be installed are listed. Click Next and review the license agreement. Accept the license agreement and click Finish to complete the installation process. If a warning for unsigned content is displayed, click OK to complete the installation process. Restart Eclipse. When Eclipse starts again, ensure that you are in the ThingWorx Extension perspective. If not, select Window->Perspective->Open Perspective->Other->ThingWorx Extension, then click OK.     NOTE: Opening any item from File->New->Other…->ThingWorx will also change the perspective to ThingWorx Extension.   You are ready to start a ThingWorx Extension Project!   Step 5: Create Extension Project   In this tutorial, you will create a ThingWorx extension that performs authentication based on your security needs.   While in the ThingWorx Extension Perspective, go to File->New->Project. Click ThingWorx->ThingWorx Extension Project.   Click Next. Enter the Project Name (for example, AuthenticatorExample). Select Gradle or Ant as your build framework. Enter the SDK location by browsing to the directory where the Extension SDK is stored. Enter the Vendor information (for example, ThingWorx Labs). Select the JRE version to 1.8. Click Finish. Your newly created project is added to the Package Explorer tab. The information from ThingWorx Extension Properties is used to populate the metadata.xml file in your project. The metadata.xml file contains information about the extension and details for the various artifacts within the extension. The information in this file is used in the import process in ThingWorx to create and initialize the entities.   Create New Authenticator   Select your project and click New -> Authenticator to create a new Authenticator.   In the new window, enter AwesomeCustomAuthenticator for the Name.   If no Server is available, create a Server using any available option. You will not need that for this guide. This Server option might be utilized based on your later needs. Enter a description to your Authenticator, such as Sample Authenticator that validates against the Thingworx User. Select Finish. You will be able to check these settings within the metadata.xml file inside of the configfiles  directory.   You will now need to add the stubs for the authenticate, issueAuthenticationChallenge, and matchesAuthRequest methods. See below for sample code and descriptions.   Method Description Constructor Needed to instantiate new objects of type AwesomeCustomAuthenticator. Instance member data/variable values in your Authenticator will not be available across requests. initializeEntity This method is called when the Authenticator Thing is saved in ThingWorx Composer, e.g. saving configuration table updates. authenticate The logic/implementation that is used to authenticate a HTTP request. issueAuthenticationChallenge Handles logic which follows authentication failure (e.g. logging an error). matchesAuthRequest This method determines if this Authenticator is valid for the authentication request type.   Below provides more information about each of these methods and some example source code:   Constructor:   A new instance of custom Authenticator class is created to handle each new HTTP request for authentication. Upon importing a custom Authenticator extension, that Authenticator is registered into AuthenticatorManager and can be managed in the ThingWorx Composer with the other system authenticators. When that custom Authenticator is enabled, it will be used in conjunction with the other configured Authenticators to attempt to authenticate HTTP requests. Any static data for each new authentication instance should be thread safe. Best to avoid putting very much logic here, even calls to get configuration or instance data (use authenticate method instead).   initializeEntity:   Read configuration data into properties as needed for Authenticator challenges. Write the LDAP server address to some static property for use across all future instances for use in Authenticator challenges. This would be a way to ensure the LDAP server location is configurable from within ThingWorx Composer. Best to update this only once (e.g. for when the first connection is made).   authenticate:   If the authentication logic/implementation fails to authenticate the HTTP request due to error in the logic or the HTTP request contained invalid data that does not pass authentication, then this implementation should throw an exception.   Example code below:   @Override public void authenticate(HttpServletRequest request, HttpServletResponse response) throws AuthenticatorException { String username = request.getHeader("User"), password = request.getHeader("Password"); if(username.isEmpty() || password.isEmpty()) throw new AuthenticatorException("User login info is empty"); try { // This section logs the latest login time and login user to a thing called MyThing // Subscribing to these properties via DataChange event will allow this information to be stored Thing LoginHelper = (Thing) EntityUtilities.findEntity("MyThing", ThingworxRelationshipTypes.Thing); LoginHelper.setPropertyValue("LatestLoginUser", new StringPrimitive(username)); LoginHelper.setPropertyValue("LatestLoginTime", new DatetimePrimitive(DateTime.now())); _logger.warn(DateTime.now() + " -- " + username + " login attempt"); // Checks that user exists and is enabled; throws exception if can't validate // May want to create user in ThingWorx if they don't exist AuthenticationUtilities.validateEnabledThingworxUser(username); // Checks that user exists and validates credentials through all configured DirectoryServices // (one is the internal directory of ThingWorx users, one could be LDAP if configured); // throws exception if can't validate AuthenticationUtilities.validateCredentials(username, password); // REQUIRED: tells rest of ThingWorx which user is logged in for purposes of permissions, etc. this.setCredentials(username); } }   issueAuthenticationChallenge:   This may not be used at all, or it may be used for alerting or logging. May be used for constructing and sending a response to the client so the client can ask the user to enter credentials again (i.e. authentication challenge). matchesAuthRequest:   Example code below. This sample code for Authenticator to automatically login the user with default username/password when specific URI used in web browser.   @Override public boolean matchesAuthRequest(HttpServletRequest httpRequest) throws AuthenticatorException { String requestURI = httpRequest.getRequestURI(); // Must access it from this URL and not from /Thingworx/Runtime/index.html#mashup=LogoutButtonMashup as // the Request URI in the latter case is always going to show as /Thingworx/Runtime/index.html if (requestURI.equals("/Thingworx/Mashups/LogoutButtonMashup")) return true; else return false; }   Below is another example of how to implement the matchesAuthRequest method. Of course, it’s not a safe method. Nevertheless, it provides input into a different way to handle things.   @Override public boolean matchesAuthRequest(HttpServletRequest request) throws AuthenticatorException { try { // DON'T DO THIS by itself -- getHeader returns null if it can't find the header, // so this is unsafe and may block other authenticators from attempting String value1 = request.getHeader("User"); String value2 = request.getHeader("Password"); // DO ADD THIS - this is safe // Optionally add some logging statement here to inform of missing headers if(value1 == null || value2 == null) return false; return true; } catch(Exception e) { // This won't normally hit. This is really for other, more complicated validation processes throw new AuthenticatorException("Missing headers"); } }   Step 6: Build Extension   You can use either Gradle or Ant to build your ThingWorx Extension Project.   Build Extension with Gradle   Right click on your project ->Gradle (STS)->Tasks Quick Launcher.   Set Project from the drop-down menu to your project name and type Tasks as build. Press Enter. This will build the project and any error will be indicated in the console window.   Your console window will display BUILD SUCCESSFUL. This means that your extension is created and stored as a zip file in your_project->build->distributions folder.   Build Extension with Ant   Go to the Package explorer -> your_project->. Right click on build-extension.xml->Run As->Ant Build.   Your console output will indicate BUILD SUCCESSFUL similar to the below text: build: [echo] Building AuthenticatorExample extension package... BUILD SUCCESSFUL Total time: 770 milliseconds   NOTE: This will build your project and create the extension zip in the AuthenticatorExample->build->distributions folder of your project.     Click here to view Part 3 of this guide.  
View full tip
  Build authentications extensions quickly and add to the security of your application.   GUIDE CONCEPT   Extensions enable you to quickly and easily add new functionality to an IoT solution. Extensions can be service (function/method) libraries, connector templates, functional widgets, and more.   These pointers and steps will enable you to maintain focus on development of your own application and still utilize the power of ThingWorx for other purposes at the same time.   When to Utilize:   You have your own login from outside of ThingWorx but you want to leverage ThingWorx user management You are using an identity provider other than ThingWorx You need to support passing of credentials in headers/query string parameters which ThingWorx doesn’t support out-of-the-box   Concept   Whether you would like ThingWorx to handle the security for your application, have an application you want ThingWorx to pump data into, or would just like to utilize ThingWorx features in your own application, external authentication can be a great way to integrate your application with ThingWorx. This guide will focus in on how to create an authentication middle man between a system you have already developed (or are in the middle of creating) and connect it to the ThingWorx Platform. In a provided demo website, you will login (with the provided credentials) and validate your user profile and password with ThingWorx. This setup shows the simple integration between ThingWorx and an application you would like to connect to the ThingWorx Platform.   YOU'LL LEARN HOW TO   Install the Eclipse plugin and extension SDK Create authentication application Build and import an extension   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL parts of this guide is 60 minutes.        Step 1: Completed Example   Download the completed files for this tutorial: AuthenticationExtension.zip   This tutorial will guide you through security concepts within ThingWorx. Utilize this file to see a finished example and return to it as a reference if you become stuck creating your own fully flushed out application.   Keep in mind, this download uses the exact names for entities used in this tutorial. If you would like to import this example and also create entities on your own, change the names of the entities you create. The download contains three directories (Source, CompletedExtension, and Demo). See below for the information about each directory.     Directory Description Source The completed project and source code to be utilized as a comparison or ready to go pre-built extension. CompletedExtension A completed and built extension that is based on the steps utilized in the latter steps. The zip file in this directory can be imported directly. Demo A demo web page that shows easy integration of an external application and ThingWorx authentication.       Step 2: Understanding Authenticators   Authentication between ThingWorx and custom outside applications begins with Authenticators.  Authenticators are the component integration point that allows for custom authentication schemes to be added into the ThingWorx platform. Authenticators can be used to retrieve content, parameters, headers, etc from HTTP requests.   The retrieved data can be verified by the authenticator using its implemented/configured verification  algorithm(s). If that data is of a username/password credential type the authenticator can choose to pass validation of that data to the configured list of Directory Services. For example, the internal ThingWorx username/password store, or delegate to an external Active Directory set of username/passwords.   ThingWorx tries to authenticate in increasing order of priority. In example, starting with  ThingworxBasicAuthenticator, unless a custom authenticator is given higher priority than that, ThingWorx will continue trying enabled authenticators by priority until one succeeds.   If an authenticator has priority 1, it will be consulted first in the chain of authenticators. If the authenticator has a priority of 101, it will be consulted after the ThingworxBasicAuthenticator (with priority of 100) fails to authenticate the HTTP request. There are several built-in authenticators   Authenticator Priority Editable ThingworxBasicAuthenticator 100 No ThingworxMobileTokenAuthenticator 150 Yes ThingworxApplicationKeyAuthenticator 200 No ThingworxSSOAuthenticator 250 Yes ThingworxFormAuthenticator 300 No ThingworxMobileAuthorizationAuthenticator 350 Yes ThingworxHttpBasicAuthenticator 400 No   When all configured and enabled authenticators fail to validate the data provided by an HTTP request, an authentication failure response is sent back to the requesting client. Custom Authenticators can be given priority such that they fit into any part of this process.   For setting the priority follow the instructions below:   Navigate to and select Security > Authenticators.   Select the Authenticator you would like to edit (ie, ThingworxSSOAuthenticator). If you do not see a specific Authenticator you would like to VIEW ONLY, check the Show System Objects checkbox in your search filter.   Update the Priority field with a new value. Click Save.       Step 3: Download Plugin and SDK   The ThingWorx Extension SDK provides supported classes and APIs to build Java-based extensions. The APIs included in this SDK allow manipulation of ThingWorx platform objects to create Java based extensions that can extend the capability of the existing ThingWorx platform.   The Eclipse Plugin assists in working with the Extension SDK to create projects, entities, and samples.   Download the Eclipse Plugin. Download Extensions SDK. Make a note of the directory where the plugin and the extension SDK are stored. The path of the directory will be required in upcoming steps. Do not extract the zip files.     Click here to view Part 2 of this guide.
View full tip
  Step 9: File Transfer Example   To handle file transfers, a virtual directory is created in the SteamSensor1 entity and in the [C SDK HOME DIR]/examples/FileTransferExample application directory. The source code used for this example is found in [C SDK HOME DIR]/examples/FileTransferExample/src/main.c.   Inside of the [C SDK HOME DIR]/examples/FileTransferExample folder, create the folder structure shown below:   /transfer/ /transfer/incoming/ /transfer/outgoing/   Inside of the /transfer/outgoing/ directory, create and open a file with the name outgoing.txt. Once the outgoing.txt document is open, add the following text, save, and close the file: Hello. This is a file coming from the client application. Navigate to the [C SDK HOME DIR]/examples/FileTransferExample/src/main.c code and update the lines below with the appropriate information for your IP, port, and the “admin_key” Application Key’s keyId value in the ThingWorx Composer:   /* Server Details */ #define TW_HOST "127.0.0.1" #define TW_PORT 80 #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c"   To support file transfers in your client application, you must use the   twFileManager_AddVirtualDir function in order to create the virtual directories in the entity with such a capability. It will also define the directories available for file operations. A virtual directory maps a unique name to an absolute path of a directory in the file system. All subdirectories of the specified directory are exposed to the server. You can define multiple virtual directories. The directories do not need to be contiguous. Staging Directory   As an optional, but recommended step, you should set the directory that the application should use for staging when performing file transfers. This can be seen in the line below and should be done before initializing the FileManager. The default directory of the FileManager is most likely owned by root and will require a change to either the location of the staging directory and the ownership of the staging directory, or running the application as a User with the correct permissions.   twcfg.file_xfer_staging_dir = "staging";   The example provided uses the TW_SHARE_DIRECTORY macro to create two virtual directories that will act as the root directories in the virtual file system of this application are added. The client is then started as follows with the necessary TW_ADD_FILE_TRANSFER_SHAPE function being called:   TW_ADD_FILE_TRANSFER_SHAPE(); TW_SHARE_DIRECTORY("in", "/transfer/incoming/"); TW_SHARE_DIRECTORY("out", "/transfer/outgoing/");   The creations of the payloads used to create the remote directories on the platform have been moved to a helper function below to make the design cleaner:   int setupSystemRepo(const char * remoteInPath, const char * remoteOutPath, const char * remoteFile);   After our remote directories and files have been setup, it is time to perform the file transfers. Normally, this would mean invoking the Copy service for a Subsystem, but two functions have been created to make this process easier:   int twFileManager_GetFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid) int twFileManager_SendFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid)   The table below displays an example of the first set of parameters:   Parameter Example Description sourceRepo SystemRepository The name of FileRepository or RemoteThing to transfer the file FROM. sourcePath outgoing The path specifying the location of the source file. sourceFile The name of the source file.   targetRepo SteamSensor1 The name of FileRepository or RemoteThing to transfer the file TO. targetPath incoming The path specifying the destination location of the file. targetFile incoming.txt The name of the file at the target. This name can differ from the sourceName. timeout 15,000 The amount of time (in seconds) to wait for a synchronous transfer to complete before cancelling the transfer. async false If false, the service call will block for timeout seconds or until the transfer completes. tid incoming0123 The unique TID associated with the file.   The C SDK also provides the ability to create a FileCallback function that the FileManager will call that function when any file transfer events occur. You can provide a wildcard filter so that only file transfer Events of files that match the filter call the callback function. In addition, callbacks can be set up as “one-shots” such that the callback is unregistered automatically after it is invoked the first time.   NOTE: An optional file transfer callback is registered in the code and provided. You will see the output from the function as files are sent and received.   After running this application, you will notice a new file in the transfer/incoming folder after refreshing. This is the file that we created in the ThingWorx Composer file system for the SystemRepository Entity and was able to copy from that location to our local project. We have also sent a file to the server’s SystemRepository. The BrowseFileSystem and GetFileListing services can be used to check for the folders and files created.   twFileManager_RegisterFileCallback(fileCallbackFunc, NULL, FALSE, NULL);     Step 10: Support Other Platforms   All Websocket errors indicate some general issue communicating with the ThingWorx platform. If you experience an issue connecting, refer to the table below for a list of websocket errors, their corresponding codes, and an explanation of the issue.   Code Message Troubleshooting 200 TW_UNKNOWN_WEBSOCKET_ERROR An unknown error occurred on the websocket. 201 TW_ERROR_INITIALIZING_WEBSOCKET An error occurred while initializing the websocket. Check your websocket configuration parameters for validity. 202 TW_TIMEOUT_INITIALIZING_WEBSOCKET A timeout occurred while initializing the websocket. Check the status of the connection to ThingWorx. 203 TW_WEBSOCKET_NOT_CONNECTED The websocket is not connected to ThingWorx. The requested operation cannot be performed. 204 TW_ERROR_PARSING_WEBSOCKET_DATA An error occurred while parsing websocket data. The parser could not break down the data from the websocket. 205 TW_ERROR_READING_FROM_WEBSOCKET An error occurred while reading data from the websocket. Retry the read operation. If necessary, resend the data. 206 TW_WEBSOCKET_FRAME_TOO_LARGE The SDK is attempting to send a websocket frame that is too large. The Maximum Frame Size is set when calling twAPI_Initialize and should always be set to the Message Chunk Size (twcfg.message_chunk_size). 207 TW_INVALID_WEBSOCKET_FRAME_TYPE The type of the frame coming in over the websocket is invalid. 208 TW_WEBSOCKET_MSG_TOO_LARGE The application is attempting to send a message that has been broken up in to chunks that are too large to fit in a frame. You should not see this error. 209 TW_ERROR_WRITING_TO_WEBSOCKET An error occurred while writing to the Web socket. 210 TW_INVALID_ACCEPT_KEY The Accept key sent earlier from ThingWorx is not valid.     Step 11: Next Steps   Congratulations! You've successfully completed the C SDK Tutorial, and learned how to utilize the resources provided in the Edge SDK to create your own application.   Learn More   We recommend the following resources to continue your learning experience:   Capability Link Build Design Your Data Model Build Implement Services, Events, and Subscriptions   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support C Edge SDK Help Center    
View full tip
  Step 6: Data Shapes   Data Shapes are an important part of creating/firing Events and also invoking Services   Define With Macros   In order to define a Data Shape 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 Data Shape without using a macro, use the  twDataShape_CreateFromEntries  function. In the example below, we are creating a Data Shape called SteamSensorReadings that has two numbers as Field Definitions.   twDataShape * ds = twDataShape_Create(twDataShapeEntry_Create("a",NULL,TW_NUMBER)); twDataShape_AddEntry(ds, twDataShapeEntry_Create("b",NULL,TW_NUMBER)); /* Name the DataShape for the SteamSensorReadings service output */ twDataShape_SetName(ds, "SteamSensorReadings");     Step 7: Events and Services   Events and Services provide useful functionality. Events are a good way to make a Service be asynchronous. You can call a Service, let it return, then your Entity can subscribe to your Event and not keep the original Service function waiting. Events are also a good way to allow the platform to respond to data when it arrives on the edge device without it having to poll the edge device for updates.   Fire Events   To fire an Event you first need to register the Event and load it with the necessary fields for the Data Shape of that Event using the twApi_RegisterEvent function. Afterwards, you would send a request to the ThingWorx server with the collected values using the twApi_FireEvent function. An example is as follows:   twDataShape * ds = twDataShape_Create(twDataShapeEntry_Create("message", NULL,TW_STRING)); /* Event datashapes require a name */ twDataShape_SetName(ds, "SteamSensorFault"); /* Register the service */ twApi_RegisterEvent(TW_THING, thingName, "SteamSensorFault", "Steam sensor event", ds); …. struct { char FaultStatus; double Temperature; double TemperatureLimit; } properties; …. properties. TemperatureLimit = rand() + RAND_MAX/5.0; properties.Temperature = rand() + RAND_MAX/5.0; properties.FaultStatus = FALSE; if (properties.Temperature > properties.TemperatureLimit && properties.FaultStatus == FALSE) { twInfoTable * faultData = 0; char msg[140]; properties.FaultStatus = TRUE; sprintf(msg,"%s Temperature %2f exceeds threshold of %2f", thingName, properties.Temperature, properties.TemperatureLimit); faultData = twInfoTable_CreateFromString("message", msg, TRUE); twApi_FireEvent(TW_THING, thingName, "SteamSensorFault", faultData, -1, TRUE); twInfoTable_Delete(faultData); }   Invoke Services   In order to invoke a Service, you will use the twApi_InvokeService function. The full documentation for this function can be found in [C SDK HOME DIR]/src/api/twApi.h. Refer to the table below for additional information.   Parameter Type Description entityType Input The type of Entity that the service belongs to. Enumeration values can be found in twDefinitions.h. entityName Input The name of the Entity that the service belongs to. serviceName Input The name of the Service to execute. params Input A pointer to an Info Table containing the parameters to be passed into the Service. The calling function will retain ownership of this pointer and is responsible for cleaning up the memory after the call is complete. result Input/Output A pointer to a twInfoTable pointer. In a successful request, this parameter will end up with a valid pointer to a twInfoTable that is the result of the Service invocation. The caller is responsible for deleting the returned primitive using twInfoTable_Delete. It is possible for the returned pointer to be NULL if an error occurred or no data is returned. timeout Input The time (in milliseconds) to wait for a response from the server. A value of -1 uses the DEFAULT_MESSAGE_TIMEOUT as defined in twDefaultSettings.h. forceConnect Input A Boolean value. If TRUE and the API is in the disconnected state of the duty cycle, the API will force a reconnect to send the request.   See below for an example in which the Copy service from the FileTransferSubsystem is called:   twDataShape * ds = NULL; twInfoTable * it = NULL; twInfoTableRow * row = NULL; twInfoTable * transferInfo = NULL; int res = 0; const char * sourceRepo = "SimpleThing_1"; const char * sourcePath = "tw/hotfolder/"; const char * sourceFile = "source.txt"; const char * targetRepo = "SystemRepository"; const char * targetPath = "/"; const char * targetFile = "source.txt"; uint32_t timeout = 60; char asynch = TRUE; char * tid = 0; /* Create an infotable out of the parameters */ ds = twDataShape_Create(twDataShapeEntry_Create("sourceRepo", NULL, TW_STRING)); res = twDataShape_AddEntry(ds, twDataShapeEntry_Create("sourcePath", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("sourceFile", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("targetRepo", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("targetPath", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("targetFile", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("async", NULL, TW_BOOLEAN)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("timeout", NULL, TW_INTEGER)); it = twInfoTable_Create(ds); row = twInfoTableRow_Create(twPrimitive_CreateFromString(sourceRepo, TRUE)); res = twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(sourcePath, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(sourceFile, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(targetRepo, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(targetPath, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(targetFile, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromBoolean(asynch)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromInteger(timeout)); twInfoTable_AddRow(it,row); /* Make the service call */ res = twApi_InvokeService(TW_SUBSYSTEM, "FileTransferSubsystem", "Copy", it, &transferInfo, timeout ? (timeout * 2): -1, FALSE); twInfoTable_Delete(it); /* Grab the tid */ res = twInfoTable_GetString(transferInfo,"transferId",0, &tid);   Bind Event Handling You may want to track exactly when your edge Entities are successfully bound to or unbound from the server. The reason for this is that only bound items should be interacting with the ThingWorx Platform and the ThingWorx Platform will never send any requests targeted at an Entity that is not bound. A simple example that only logs the bound Thing can be seen below. After creating this function, it will need to be registered using the twApi_RegisterBindEventCallback function before the connection is made.   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); } …. twApi_RegisterBindEventCallback(thingName, BindEventHandler, NULL);   OnAuthenticated Event Handling   You may also want to know exactly when your Edge device has successfully authenticated and made a connection to the ThingWorx platform. Like the bind Event handling, this function will need to be made and registered. To register this handler, use the   twApi_RegisterOnAuthenticated Callback function before the connection is made. This handler form can also be used to do a delay bind for all Things.   void AuthEventHandler(char * credType, char * credValue, void * userdata) { if (!credType || !credValue) return; TW_LOG(TW_FORCE,"AuthEventHandler: Authenticated using %s = %s. Userdata = 0x%x", credType, credValue, userdata); /* Could do a delayed bind here */ /* twApi_BindThing(thingName); */ } … twApi_RegisterOnAuthenticatedCallback(AuthEventHandler, NULL);     Step 8: Tasks   If you are using the built-in Tasker to drive data collection or other types of repetitive or periodic activities, create a function for the task. Task functions are registered with the Tasker and then called at the rate specified after they are registered. The Tasker is a very simple, cooperative multitasker, so these functions should not take long to return and most certainly must not go into an infinite loop.   The signature for a task function is found in [C SDK HOME DIR]/src/utils/twTasker.h. The function is passed a DATETIME value with the current time and a void pointer that is passed into the Tasker when the task is registered. After creating this function, it will need to be registered using the twApi_CreateTask function after the connection is created. Below shows an example of creating this function, registering this function, and how this function can be used.   #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("message", msg, TRUE); twApi_FireEvent(TW_THING, thingName, "SteamSensorFault", faultData, -1, TRUE); twInfoTable_Delete(faultData); } /* Update the properties on the server */ sendPropertyUpdate(); } … twApi_CreateTask(DATA_COLLECTION_RATE_MSEC, dataCollectionTask); … while(1) { char in = 0; #ifndef ENABLE_TASKER DATETIME now = twGetSystemTime(TRUE); twApi_TaskerFunction(now, NULL); twMessageHandler_msgHandlerTask(now, NULL); if (twTimeGreaterThan(now, nextDataCollectionTime)) { dataCollectionTask(now, NULL); nextDataCollectionTime = twAddMilliseconds(now, DATA_COLLECTION_RATE_MSEC); } #else in = getch(); if (in == 'q') break; else printf("\n"); #endif twSleepMsec(5); }   Click here to view Part 4 of this guide
View full tip
  Step 5: Properties   In the Delivery Truck application, there are three Delivery Truck Things. Each Thing has a number of Properties based on its location, speed, and its deliveries carried out. In this design, when a delivery is made or the truck is no longer moving, the Property values are updated.   The deliveryTruck.c helper C file is based on the DeliveryTruck Entities in the Composer. After calling the construct function, there are a number of steps necessary to get going. For the SimpleThing application, there are a number of methods for creating Properties, Events, Services, and Data Shapes for ease of use.   Properties can be created in the client or just registered and utilized. In the  SimpleThingClient  application, Properties are created. In the DeliveryTruckClient application, Properties are bound to their ThingWorx Platform counterpart. Two types of structures are used by the C SDK to define Properties when it is seen fit to do so and can be found in [C SDK HOME DIR]/src/api/twProperties.h:   Name Structure Description Property Definitions twPropertyDef Describes the basic information for the Properties that will be available to ThingWorx and can be added to a client application. Property Values twProperty Associates the Property name with a value, timestamp, and quality.   NOTE: The C SDK provides a number of Macros located in [C SDK HOME DIR]/src/api/twMacros.h. This guide will use these Macros while providing input on the use of pure function calls.   The Macro example below can be found in the main source file for the   SimpleThingClient   application and the accompanying helper file simple_thing.c.   TW_PROPERTY("TempProperty", "Description for TempProperty", TW_NUMBER); TW_ADD_BOOLEAN_ASPECT("TempProperty", TW_ASPECT_ISREADONLY,TRUE); TW_ADD_BOOLEAN_ASPECT("TempProperty", TW_ASPECT_ISLOGGED,TRUE); NOTE: The list of aspect configurations can be seen in [C SDK HOME DIR]/src/api/twConstants.h. 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.   For the DeliveryTruckClient, we registered, read, and update Properties without using the Property definitions. Which method of using Properties is based on the application being built.   NOTE: Updating Properties in the ThingWorx Platform while the application is running, will update the values in the client application. To update the values in the platform to match, end the Property read section of your property handler function with a function to set the platform value.   The createTruckThing function for the deliveryTruck.c source code takes a truck name as a parameter and is used to register the Properties, functions, and handlers for each truck.   The updateTruckThing function for the deliveryTruck.c source code takes a truck name as a parameter and is used to either initialize a struct for DeliveryTruck Properties, or simulate a truck stop Event, update Properties, then fire an Event for the ThingWorx platform.   Connecting properties to be used on the platform is as easy as registering the property and optionally adding aspects. The following shows the properties that correlate to those in the DeliveryTruck entities in the Composer. To do this within the code, you would use the  TW_PROPERTY macro as shown in the deliveryTruck.c. This macro must be proceeded by either TW_DECLARE_SHAPE, TW_DECLARE_TEMPLATE or TW_MAKE_THING because these macros declare variables used by the TW_PROPERTY that follow them.   //TW_PROPERTY(propertyName,description,type) TW_PROPERTY(PROPERTY_NAME_DRIVER, NO_DESCRIPTION, TW_STRING); TW_PROPERTY(PROPERTY_NAME_DELIVERIES_LEFT, NO_DESCRIPTION, TW_NUMBER); TW_PROPERTY(PROPERTY_NAME_TOTAL_DELIVERIES, NO_DESCRIPTION, TW_NUMBER); TW_PROPERTY(PROPERTY_NAME_DELIVERIES_MADE, NO_DESCRIPTION, TW_NUMBER); TW_PROPERTY(PROPERTY_NAME_LOCATION, NO_DESCRIPTION, TW_LOCATION); TW_PROPERTY(PROPERTY_NAME_SPEED, NO_DESCRIPTION, "TW_NUMBER);   Read Properties   Reading Properties from a ThingWorx platform Thing or the returned Properties of a Service can be done using the TW_GET_PROPERTY macro. Examples of its use can be seen in all of the provided applications. An example can be seen below:   int flow = TW_GET_PROPERTY(thingName, "TotalFlow").number; int pressue = TW_GET_PROPERTY(thingName, "Pressure").number; twLocation location = TW_GET_PROPERTY(thingName, "Location").location; int temperature = TW_GET_PROPERTY(thingName, "Temperature").number;   Write Properties   Writing Properties to a ThingWorx platform Thing from a variable storing is value uses a similarly named method. Using the TW_SET_PROPERTY macro will be able to send values to the platform. Examples of its use can be seen in all of the provided applications. An example is shown below:   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));   This macro utilizes the twApi_PushSubscribedProperties function call to pushe all property updates to the server. This can be seen in the updateTruckThing function in deliveryTruck.c.   Property Change Listeners   Using the Observer pattern, you can take advantage of the Property change listener functionality. With this pattern, you 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, call the twExt_AddPropertyChangeListener function using the:   Name of the Thing (entityName) Property this listener should watch Function that will be called when the property has changed 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   In order to release the memory for your application when done with utilizing listeners for the Property, call the twExt_RemovePropertyChangeListener function.   void simplePropertyObserver(const char * entityName, const char * thingName,twPrimitive* newValue){ printf("My Value has changed\n"); } twExt_RemovePropertyChangeListener(simplePropertyObserver);   Click here to view Part 3 of this guide  
View full tip
  Use the C SDK to build an app that connects to ThingWorx with persistent bi-directional communication.     GUIDE CONCEPT   This project will introduce more complex aspects of the ThingWorx C SDK and help you to get started with development.   Following the steps in this this guide, you will be ready to develop your own IoT application with the ThingWorx C SDK.   We will teach you how to use the C programming language to connect and build IoT applications to be used with the ThingWorx Platform.   YOU'LL LEARN HOW TO   Establish and manage a secure connection with a ThingWorx server, including SSL negotiation and connection maintenance Enable easy programmatic interaction with the Properties, Services, and Events that are exposed by Entities running on a ThingWorx server Create applications that can be directly used with your device running the C programming language Basic concepts of the C Edge SDK How to use the C Edge API to build a real-world application How to utilize resources provided in the Edge SDK to help create your own application    Note: The estimated time to complete ALL 4 parts of this guide is 60 minutes.      Step 1: Completed Examples   Download the completed files for this tutorial: ThingWorx C Edge SDK Sample Files.zip.   This tutorial will guide you through working with the C SDK on differing levels. Utilize this file to see a finished example and return to it as a reference if you become stuck creating your own fully fleshed out application.   Keep in mind, this download uses the exact names for Entities used in this tutorial. If you would like to import this example and also create Entities on your own, change the names of the Entities you create.     Step 2: Environment Setup   In order to compile C code, you need a C compiler and the ThingWorx C Edge SDK. It will be helpful to have CMake installed on your system. CMake is a build tool that will generate make or project files for many different platforms and IDEs.   Operating System Notes Windows You will need a 3rd party compiler such as MinGW GCC, Cygwin GCC or you can follow these Microsoft instructions to download and use the Microsoft Visual C++ Build Tool. Mac Download the Apple Developer Tools. Linux/Ubuntu A compiler is included by default.   NOTE: You can use CMake, version 2.6.1 or later to build projects or make files, which then are used to build the applications that you develop with the C SDK.   Before you can begin developing with the ThingWorx C SDK, you need to generate an Application Key and modify the source code file. You can use the Create an Application Key guide as a reference.   Modify Source File   Extract the files from the C SDK samples zip file. At the top level of the extracted files, you will see a folder called examples. This directory provides examples of how to utilize the C SDK. Open a terminal, go to your workspace, and create a new directory. You can also just switch to the unzipped directory in your system. After you've created this directory in your workspace, copy the downloaded files and folders into your new directory. You can start creating your connection code or open the main.c source file in the examples\SteamSensor\src directory for an example.   Operating System Code Linux/Ubuntu gedit main.c OR vi main.c Mac open –e main.c Windows start main.c        5. Modify the Server Details section at the top with the IP address for your ThingWorx Platform instance and the Application Key you would like to use.   Change the TW_HOST definition accordingly. Change the TW_PORT definition accordingly. Change the TW_APP_KEY definition to the keyId value saved from the last step.   /* Server Details */ #define TW_HOST "https://pp-XXXXXXXXX.devportal.ptc.i" #define TW_PORT 80 #define TW_APP_KEY "e1d78abf-cfd2-47a6-92b7-37ddc6dd34618" NOTE: Using the Application Key for the default Administrator is not recommended. If administrative access is absolutely necessary, create a User and place the user as a member of Admins.   Compile and Run Code   To test your connection, you will only need to update the main.c in the SteamSensor example folder. CMake can generate Visual Studio projects, make build files or even target IDEs such as Eclipse, or XCode. CMake generates a general description into a build for your specific toolchain or IDE.   Inside the specific example folder you would like to run, ie SteamSensor. Create a directory to build in, for this example call it bin. mkdir bin  cd bin      5. Run the CMake command listed below. This assumes CMake is already on your PATH. cmake ..      6. CMake has now produced a set of project files which should be compatible with your development environment.   Operating System Command Note Unix make A set of make files Windows msbuild tw-c-sdk.sln /t:build A visual studio solution   NOTE: CMake does its best to determine what version of Visual Studio you have but you may wish to specify which version to use if you have more than one installed on your computer. Below is an example of forcing CMake to use a specific version of Visual Studio: cmake -G "Visual Studio 15 2017" .. If your version of Visual Studio or other IDE is unknown, use cmake -G to see a list of supported IDEs.   You also have the alternative of opening the tw-c-sdk.sln from within Visual Studio and building in this IDE.   NOTE: By default, CMake will generate a build for the creation of a release binary. If you want to generate a debug build, use the command-> cmake -DBUILD_DEBUG=ON ..       7. Once your build completes you will find the build products in the CMake directory (see example below). From here, open the project in your IDE of choice.   NOTE: You should receive messages confirming successful binding, authentication, and connection after the main.c file edits have been made.   Operating System Files Description Unix ./bin/src/libtwCSdk_static.a  Static Library Unix ./bin/src/libtwCSdk.so  Shared Library Unix ./bin/examples/SteamSensor/SteamSensor   Sample Application Windows .\bin\src\<Debug/Release>\twCSdk_static.lib  Static Library Windows .\bin\src\<Debug/Release>\twCSdk.dll  Shared Library Windows .\bin\examples\<Debug/Release>\SteamSensor\SteamSensor.exe  Sample Application     Step 3: Run Sample Code   The C code in the sample download is configured to run and connect to the Entities provided in the ThingWorxEntitiesExport.xml file. Make note of the IP address of your ThingWorx Composer instance. The top level of the exported zip file will be referred to as [C SDK HOME DIR].   Navigate to the [C SDK HOME DIR]/examples/ExampleClient/src directory. Open the main.c source file.   Operating System Command Linux/Ubuntu gedit main.c OR vi main.c Mac open –e main.c Windows start main.c   Modify the Server Details section at the top with the IP address for your ThingWorx Platform instance and the Application Key you would like to use. Change the TW_HOST definition accordingly.   NOTE: By default, TW_APP_KEY has been set to the Application Key from the admin_key in the import step completed earlier. Using the Application Key for the default Administrator is not recommended. If administrative access is absolutely necessary, create a user and place the user as a member of the Admins security group.   /* Server Details */ #define TW_HOST "127.0.0.1" #define TW_APP_KEY "ce22e9e4-2834-419c-9656-e98f9f844c784c"   If you are working on a port other than 80, you will need to update the conditional statement within the main.c source file. Search for and edit the first line within the main function. Based on your settings, set the int16_t port to the ThingWorx platform port. Click Save and close the file. Create a directory to build in, for this example call it bin.   Operating System Command Linux/Ubuntu mkdir bin Mac mkdir bin Windows mkdir bin   Change to the newly created bin directory.   Operating System Command Linux/Ubuntu cd bin Mac cd bin Windows cd bin   Run the CMake command using your specific IDE of choice.    NOTE: Include the two periods at the end of the code as shown below. Use cmake -G to see a list of supported IDEs.   cmake ..   Once your build completes, you will find the build products in the bin directory, and you can open the project in your IDE of choice. NOTE: You should receive messages confirming successful binding, authentication, and connection after building and running the application    10. You should be able to see a Thing in your ThingWorx Composer called SimpleThing_1 with updated last Connection and isConnected properties. SimpleThing_1 is bound for the duration of the application run time                                                                                                                                                                                The below instructions will help to verify the connection.   Click Monitoring. Click Remote Things from the list to see the connection status.   You will now be able to see and select the Entity within the list.   Step 4: ExampleClient Connection   The C code provided in the main.c source file is preconfigured to initialize the ThingWorx C Edge SDK API with a connection to the ThingWorx platform and register handlers. In order to set up the connection, a number of parameters must be defined. This can be seen in the code below.   #define TW_HOST "127.0.0.1" #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c #if defined NO_TLS #define TW_PORT = 80; #else #define TW_PORT = 443; #endif The first step of connecting to the platform: Establish Physical Websocket, we call the   twApi_Initialize function with the information needed to point to the websocket of the ThingWorx Composer. This function:   Registers messaging handlers Allocates space for the API structures Creates a secure websocket   err = twApi_Initialize(hostname, port, TW_URI, appKey, NULL, MESSAGE_CHUNK_SIZE, MESSAGE_CHUNK_SIZE, TRUE); if (TW_OK != err) { TW_LOG(TW_ERROR, "Error initializing the API"); exit(err); }   If you are not using SSL/TLS, use the following line to test against a server with a self-signed certificate:   twApi_SetSelfSignedOk();   In order to disable HTTPS support and use HTTP only, call the twApi_DisableEncryption function. This is needed when using ports such as 80 or 8080. A call can be seen below:   twApi_DisableEncryption();   The following event handlers are all optional. The twApi_RegisterBindEventCallback function registers a function that will be called on the event of a Thing being bound or unbound to the ThingWorx platform. The twApi_RegisterOnAuthenticatedCallback function registered a function that will be called on the event the SDK has been authenticated by the ThingWorx Platform.  The twApi_RegisterSynchronizeStateEventCallback function registers a function that will be called after binding and used to notify your application about fields that have been bound to the Thingworx Platform.   twApi_RegisterOnAuthenticatedCallback(authEventHandler, TW_NO_USER_DATA); twApi_RegisterBindEventCallback(NULL, bindEventHandler, TW_NO_USER_DATA); twApi_RegisterSynchronizeStateEventCallback(NULL, synchronizeStateHandler, TW_NO_USER_DATA);   NOTE: Binding a Thing within the ThingWorx platform is not mandatory, but there are a number of advantages, including updating Properties while offline.   You can then start the client, which will establish the AlwaysOn protocol with the ThingWorx Composer. This protocol provides bi-directional communication between the ThingWorx Composer and the running client application. To start this connection, use the line below:   err = twApi_Connect(CONNECT_TIMEOUT, RETRY_COUNT); if(TW_OK != err){ exit(-1); }     Click here to view Part 2 of this guide
View full tip
  GUIDE CONCEPT   This guide introduces connecting an Allen-Bradley PLC to ThingWorx Kepware Server.   YOU'LL LEARN HOW TO   Create and run a simple ladder logic application on an Allen-Bradley PLC Connect the PLC to 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:        1. Connected Components Workbench       2. ThingWorx Kepware Server       3. ThingWorx Foundation (for Windows)   In this continued step, you'll now connect an Allen-Bradley PLC to Connected Components Workbench and then to ThingWorx Kepware Server.   In a later guide, we'll propogate that information further from ThingWorx Kepware Server into ThingWorx Foundation.   NOTE: Both Rockwell Automation's Connected Components Workbench and ThingWorx Kepware Server are time-limited trials. If significant time has passed while persuing this Learning Path, you may need to reinitialize them. Consult the Troubleshooting step of this guide for more information.       Step 2: Setup PLC   This guide uses an inexpensive Allen-Bradley Micro820 PLC as a demonstration.   ThingWorx Kepware Server offers drivers for hundreds of devices, making this step the only one that contains device-specific instructions.   Read and understand installation instructions before making any electrical connections to the PLC.   1. Connect the postive lead of a 24V power supply along with a 6" test lead to Terminal 1 of the output terminal block.   2. Connect the negative lead of the power supply to Terminal 2.     3. Confirm the test lead is secure from making contact with anything conductive; it will be  connected to +24V. Power on the supply and confirm the LEDs briefly light.       4. Carefully touch the test lead to the Input 1 terminal and confirm the indicator LED for Input 1 turns on.     5. Power off the supply before continuing to the next step.       Step 3: Create PLC Project   In this step, you will create a simple PLC application. This application will connect to a ThingWorx Mashup in subsequent guides in the Learning Path.    1. After opening Connected Components Workbench, click New... in the Project section.   2. Enter ThingWorxGuide in the Name field and click Create.   3. Browse to the PLC model you are using and click Select, then Add to Project.     4. Right-click Program, then left-click Add > New LD: Ladder Diagram     5. Double-click Prog1 to open the ladder window.     Ladder Logic   You will create a simple application that will turn on output 2 when there is a signal on input 2.    1.. Right-click in the box to the left of the rung, hover over Insert Ladder Elements, then click on Direct Coil   .     2. Click the I/O - Micro820 tab towards the right and select an output coil - this guide uses _IO_EM_DO_02. Then click OK                  3. Add an input contact by right-clicking in the box to the left of the rung, hover over Insert Ladder Elements, then click on Direct Contact.   4. Click the I/O - Micro820 tab and scroll down to select an input - this guide uses _IO_EM_DI_02. Then click OK.        5. The program window should now look like this:     Upload   Next, you will propagate the program to the PLC.   1. Secure the test lead then apply power to the PLC.   2. Connect an ethernet cable directly between the PLC and your Windows computer.   3. Click Device > Connect to connect to the PLC; a pop-up will appear saying the project does not match the program in the controller.     NOTE: When either your PLC or computer are restarted, they may be assigned a new IP address, requiring you to reconfigure the connection. Click the tab labled with your PLC, then click the pencil icon next to connection path, click Browse, expand the Ethernet driver, highlight the active controller, and click OK. Click Close and then Connect.       4. Click Download current project to the controller   5. Confirm overwriting any program in the controller by clicking Download.   6. After your project is downloaded, run it on the controller by clicking Yes.     7. Touch the test lead to the I-02 terminal, and your program will turn on the #2 output. You can confirm your project is working by both hearing the soft click from the PLC and seeing the output indicator turn on.       Step 4: Configure ThingWorx Kepware Server   Now that you have a simple project running on the PLC, you need to configure ThingWorx Kepware Server to monitor it.   1. Open ThingWorx Kepware Server, right-click on Connectivity, and click New Channel.   2. Select Allen-Bradley Micro800 Ethernet from the drop-down, then click Next.       3. Click Next to accept the defaults, and click Finish to create Channel2.   4. Click Click to add a device below Channel2, enter myPLC in the name field, and click Next.   5. Enter the IP address of your PLC, then click Next. The IP address of your PLC is shown in Connected Components Workbench in Device > Configure.       NOTE: The IP address of the PLC may change when it is power cycled and must be updated in ThingWorx Kepware Server to match   6. Click Next to accept default values for each pop-up, and click Finish to create the myPLC device.       7. Click the Click to add a static tag message.   8. Enter Coil2 in the Name field, _IO_EM_DO_02 in the Address field, change the Data Type drop-down to Boolean, and click OK.  The address must exactly match a variable name in the PLC.       9. Create a second tag by right-clicking on myPLC again and clicking New Tag.   10. Enter Coil3 in the Name field, _IO_EM_DO_03 in the Address field, select Boolean from the Data Type drop-down, and click OK.         Step 5: Troubleshooting   1. 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 icon in system tray.     Click Stop Runtime service. Wait a minute for the process to stop, then click Start Runtime service.   2.  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 Connect to an Allen-Bradley PLC tutorial. You've learned how to:   Create and upload a simple ladder logic application to a PLC Connect a PLC to ThingWorx Kepware Server   The next guide in the Using an Allen-Bradley PLC with ThingWorx learning path is Create an Application Key.   Learn More   Capability Resource Analyze Monitor an SMT Assembly Line     Additional Resources   For additional information on ThingWorx Kepware Server:   Resource Link Website Connecting & Managing Industrial Assets Documentation Kepware documentation Support Kepware Support site
View full tip
Announcements