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

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

IoT Tips

Sort by:
  Explore the ThingWorx Foundation IoT application-building platform in a convenient video format.     Guide Concept   This project will introduce you to the principles of ThingWorx Foundation by creating a working web application, guided by a convenient video.   Following the steps in this guide, you will create the building blocks of your first application for the Internet of Things (IoT). You will use ThingWorx Composer to create Thing Templates, which are then used to create Things that model the application domain. A simulator is imported to generate time-series data that is saved to a Value Stream.   After modeling the application in ThingWorx Composer, you'll use Mashup Builder to create the web application Graphical User Interface (GUI).   You'll learn how to   Create a Thing Shape, Thing Template, and Thing Store data in a Value Stream Download and install a data simulator Create an application UI    NOTE:  The estimated time to complete this guide is 30 minutes     Step 1: Video   Click the link below to enjoy the video.   Get Started with ThingWorx for IoT       Step 2: Next Steps   Congratulations! You've successfully completed the Get Started with ThingWorx for IoT Video Guide, and learned how to:   Use Composer to create a Thing based on Thing Shapes and Thing Templates Store Property change history in a Value Stream Define application logic using custom defined Services and Subscriptions Create an application UI with Mashup Builder Display data from connected devices Test a sample application   Learn More   We recommend the following resources to continue your learning experience:    Capability     Guide Connect Choose a Connectivity Method Build Design Your Data Model Experience Create Your Application UI   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support Getting Started with ThingWorx
View full tip
  Step 4: Data Tables (cont.) Set Properties We now have the Thing with Properties that we want logged, the Service to do said logging, and the Data Table to where the values will be stored   At the top, click Properties and Alerts. Note Data_Table_Test_Thing’s Index_Property and Value_Property.   On the Index_Property line under the Value column, click the "Pencil" icon for Set value of property.   In the slide-out on the right, enter 1.   At the top-right, click the "Check" button for Set. On the Value_Property line under the Value column, click the "Pencil" icon for Set value of property. In the slide-out on the right, enter 10.   At the top-right, click the "Check" button for Set. At the top, click Save.     Store to Data Table At the top, click Services.   On the Add_Data_Table_Entry_Service line under the Execute column, click the "Play" icon for Execute service. A pop-up will open.   At the bottom-right, click Execute. At the bottom-right, click Done. Retrieve from Data Table Return to Test_Data_Table.   At the top, click Services. Scroll down and locate the QueryDataTableEntries built-in Service.   On the QueryDataTableEntries line, click the "Play" icon for Execute service. A pop-up will open. On the bottom-right of the pop-up, click Execute. Note that you should see a single entry, showing the Index_Field at 1 and the the Value_Field at 10   On the bottom-right, click Done. If so desired, you may repeat the previous steps to add additional entries to the Data Table. You will note that the Index and Value fields of the Data Table continue to change in each entry to whatever you have set. Utilizing the functionality of the QueryDataTableEntries built-in Service was just a way to show that the Index and Value items had been correctly logged to the external Data Table. If you wanted to visualize the Data Tables in a grid, it would be as simple as utilizing the Grid Widget and tying Test_Data_Table -> QueryDataTableEntries -> All Data to said Grid. Step 5: Info Tables Just like with Streams and Data Tables, an Info Table requires a Data Shape to format it. In this example, we'll actually use the exact same Data Shape we previously created for the Stream. Create Thing Info Tables are another way to perform non-time-series data storage within the ThingWorx platform. Info Tables used for storage are tied directly to a particular Thing. As such, they are somewhat non-optimal for situations where you’re wanting to aggregate data across multiple Things. Info Tables are a Property Base Type in ThingWorx, in the same manner as a Number, Integer, or String. On the ThingWorx Composer Browse tab, click Modeling > Things, + New.   In the Name field, enter Test_Info_Table_Thing. If Project is not already set, search for and select PTCDefaultProject. In the Thing Template field, search for and select GenericThing.   At the top, click Properties and Alerts. Click + Add. In the Name field, enter Info_Table_Property. Change the Base Type to INFOTABLE. In the Data Shape field, search for and select Test_Data_Shape. This is the same Data Shape we previously created for the Stream. We're just reusing it for formatting the Info Table. Check the Persistent checkbox.   At the top-right, click the "Check" button for Done. At the top, click Save.     Set First Value Now that we have a Thing with an Info Table Property (formatted by our Data Shape), you can set some values for later display in a Mashup. On the new Info_Table_Property line under the Value column, click the "Pencil" button for Set value of property.   On the new pop-up, click the + Add button.   In the Index_Field, enter 1. In the Value_Field, enter 11.   At the bottom-right of the pop-up, click Add. Set Second Value On the pop-up, click the + Add button. In the Index_Field, enter 2. In the Value_Field, enter 22.   At the bottom-right of the pop-up, click Add. Set Third Value On the pop-up, click the + Add button. In the Index_Field, enter 3. In the Value_Field, enter 33.   At the bottom-right of the pop-up, click Add.   At the bottom-right of the pop-up, click Save. At the top, click Save.     Create Mashup Now that we have a Thing with an InfoTable Property and some value-entries in said InfoTable, let's create a Mashup to display those values by using the Grid Widget. On the ThingWorx Composer Browse tab, click VISUALIZATION > Mashups, + New.   On the New Mashup pop-up, leave the defaults, and click OK.   In the Name field, enter Test_Info_Table_Mashup. If Project is not already set, search for and select PTCDefaultProject.  At the top, click Save.   At the top, click Design. With the Widgets tab selected in the top-left, drag-and-drop a Grid Advanced Widget onto the central Canvas area.     Bind Data On the far-right, ensure that the Data tab is selected. Note that you may have to expand this area from the far-right.   Click the + icon. The Add Data pop-up will appear.   In the Entity Filter field, search for and select Test_Info_Table_Thing. In the Services Filter field, enter getprop. Click the right arrow beside the GetPropertyValues Service. On the right under Selected Services, check the Execute on Load checkbox.   At the bottom-right of the pop-up, click Done. Note that Test_Info_Thing -> GetPropertyValues is now available under the Data tab at the far-right. Expand GetPropertyValues > Returned Data > All Data.   Drag-and-drop GetPropertyValues > Returned Data > All Data > Info_Table_Property onto the Grid Advanced Widget in the central Canvas area.   On the Select Binding Target pop-up, select Data.   At the top, click Save. At the top, click View Mashup.   The new Mashup displays all of the Index and Value fields you had previously entered. If you were to add additional entries to the Info Table Property and then refreshed the Mashup, you would see those additional entries as well.   Step 6: Next Steps Congratulations! In this guide, you've learned how to: Differentiate between data storage methods Create a Data Shape to format a Stream, Data Table, and Info Table Create a Value Stream and Stream to store Time-Series Data Create a Data Table and Info Table to store non-Time-Series Data Use built-in methods to log data to a Value Stream or Info Table Create custom Services which log data to a Stream or Data Table Confirm data storage value changes via a built-in Service or Grid Widget Learn More   We recommend the following resources to continue your learning experience:     Capability Guide Build Implement Services, Events, and Subscriptions Additional Resources   If you have questions, issues, or need additional information, refer to:          Resource  Link Community Developer Community Forum Support Data Storage Help Center
View full tip
    Step 5: Tie Data to Widgets   The Mashup now has access to the backend data via get/set Data Services.   In this step, you will tie these Data Services to the Checkbox Widgets to pull and push information.   Click the Data tab in the upper right   Under GetProperties, click and drag the arrow next to Channel2_myPLC_Coil2 onto the Left Checkbox. On the Select Binding Target pop-up, click State.   Click the Data tab again Drag Channel2_myPLC_Coil3 onto the right Checkbox. On the Select Binding Target pop-up, click State.   Enable Automatic Updates   The GetProperties Mashup Data Service will now propagate the State of Coil2 and Coil3 from the PLC onto these Checkbox Widgets.   The GetProperties Service will be called automatically when the Mashup loads, so the Checkboxes states will be accurate on initial viewing.   However, the backend data state changes, you will need the GetProperties Service to be automatically called again to update the Checkbox Widgets.   Fortunately, it is simple to trigger this behavior.   Click the Data tab Click GetProperties to select it.   On the right of the Mashup Builder, Click the Data Properties tab     Click the Automatically Update Values checkbox   Allow Bidirectional Sets   You also want to enable bi-directional communication, not only displaying the current value of the PLC, but also setting it via the Mashup GUI.   The SetProperties Mashup Data Service can accomplish this.   Click the Right Checkbox to select it.   Click the Checkbox Widget's top-left drop-down menu to expose the available options.   Drag State over the Data tab to expand it. Drop onto SetProperties > Channel2_myPLC_Coil3.   Click the right Checkbox drop-down menu again.   Click Configure Bindings.   Click the down arrow to the right of Changed.   Click Add Trigger Service. Click the Data tab. Select the setProperties check box.   Click Next to close the Trigger Services window. Click Done to close the Configure Bindings pop-up. At the top, click Save.     Step 6: View Mashup    Your Mashup is now complete with two Checkbox Widgets and connections from those Widgets to the backend data.   The left Checkbox represents Coil2, and will change its state depending on whether you have touched the lead to the appropriate input on the PLC.   The right Checkbox represents Coil3, and will display the current status as well as allow you to set the status of Output Coil 3 via checking or unchecking the box.   At the top, click View Mashup to display your web application. You may need to set your browser to allow pop-ups.     Select the right checkbox. Note how the PLC's Output Coil 3 will immediately turn on.   Touch the lead to the PLC's I-02, i.e. Input 2. The left checkbox will indicate the status of Input 2 within a couple of seconds. Step 7: Troubleshooting   If the connection to the PLC stops working and there is a Thumbs Down icon next to your properties, the ThingWorx Kepware Server trial edition drivers are not connected to your PLC. The trial edition stops running after 2 hours and must be stopped and restarted. Right-click on ThingWorx Kepware Server icon in system tray.     Click Stop Runtime service. Wait a minute for the process to stop, then click Start Runtime service. If Connected Components Workbench does not connect to PLC, check the IP address of the PLC using RS Linx Classic software that was installed as part of Connected Components Workbench. RS Linx Classic is located Start > All Programs > Rockwell Software > RSLinx > RSLinx Classic Click AB_ETHIP-1, Ethernet and IP addresses of connected PLCs will be discovered NOTE: A changed PLC IP Address (typically seen through Connected Components Workbench) will require an IP Address change in ThingWorx Kepware Server settings.     Step 8: Next Steps   Congratulations! You've successfully completed the Visualize an Allen-Bradley PLC guide.   In addition, assuming you have been utilizing this guide as part of the Rockwell Automation Learning Path, this represents the end of your journey.   You've learned how to:   Create a Mashup Add Widgets Access backend data via Mashup Data Services Tie data to Widgets Create a simple web application that monitors and controls a PLC   This is the last guide in the Using an Allen-Bradley PLC with ThingWorx learning path. Learn More   Capability Resource Analyze Monitor an SMT Assembly Line Additional Resources   For additional information on ThingWorx Kepware Server:   Resource Link Documentation Kepware documentation Support Kepware Support site
View full tip
    Generate engine-failure predictions and gain insight into your data with machine learning.   GUIDE CONCEPT   This guide will upload captured data from an Edge MicroServer (EMS) "Engine Simulator" to ThingWorx Analytics Builder.   Following the steps in this guide, you will create an analytical model, and then refine it based on further information from the Analytics platform.   We will teach you how to determine whether or not a model is accurate and how you can optimize both your data inputs and the model itself.   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL parts of this guide is 60 minutes     YOU'LL LEARN HOW TO   Load an IoT dataset Generate machine learning predictions Evaluate the analytics output to gain insight     Step 1: Scenario   In this guide, we’re continuing the same MotorCo scenario, where an engine can fail catastrophically in a low-grease condition.   In previous guides, you’ve gathered and exported engine vibration-data from an Edge MicroServer (EMS).   The goal of this guide is to now import that previously-exported Comma-Separated Values (.csv) data into ThingWorx Analytics, and then create an analytical model for predictive maintenance.   Analytical model creation can be extremely helpful for the automotive segment in particular. For instance, each car that comes off the factory line could have an EMS constantly sending data from which an analytical model could automatically detect engine trouble.   This could enable your company to offer an engine monitoring subscription service to your customers.   This guide will show you how to build an analytic model of your engine to facilitate this monitoring service.     Step 2: Upload Simulated Data   This guide assumes that you are using either the hosted trial (with has both Foundation and Analytics pre-installed) or a combination of the Foundation and Analytics downloadable installers.   To confirm that Foundation is communicating with Analytics, perform the following steps:   On the ThingWorx Foundation left-side navigation column, click Analytics > Analytics Builder > Settings.   At the top-right in the Analytics Server Version field, ensure that you see an appropriate version number.     NOTE:  If you use your own dataset, it's possible that you're results in the following steps will differ from those created by the provided-dataset. If you were unable to generate a 30,000+ entry dataset in the last guide, then you may download testCSVfile.csv attached here,instead. You will also need to download and extract vibration_metadata.zip which describes each column of the dataset. On the left, click Analytics Builder > Data.   Under Datasets, click New....   In the Dataset Name field, enter simulated_dataset. In the File Containing Dataset Data section, search for and select testCSVfile.csv. In the File Containing Dataset Field Configuration section, search for and select vibration_metadata.json.   Click Submit. Note that the time it takes to import the dataset is determined by its size.       Step 3: Simulated Signals and Profiles    The Signals section of ThingWorx Analytics looks for the most statistically correlated single field in the dataset which relates to your selected goal.   This doesn't necessarily indicate that it is the cause of your goal, whether maximizing or minimizing. It just means that the dataset indicates that this single field happens to correlate with the goal that you desire.   On the left, click Analytics Builder > Signals.   At the top, click New….   In the Signal Name field, enter simulated_signal. In the Dataset field, select simulated_dataset.   Click Submit. Wait ~30 seconds for Signal State to change to COMPLETED     Unfortunately, our results aren't very good. Or, more accurately, they're too good.   Our simulated dataset has some noise in it from adding random values to our five frequency bands on each our two sensors. However, ThingWorx Analytics has instantly seen through that noise and discarded it. Instead, it's only detected that s2_fb5 isn't relevant.   If you look back at the Use the EMS to Create an Engine Simulator guide, you'll see that s2_fb5 has the same base value between both a "good grease" and a "bad grease" condition, i.e. a base of 190.   This does show already that Analytics is working, though. Since s2_fb5 didn't change between good and bad grease conditions, our Signal analysis is indicating that it's not relevant to our model.   Profiles   Now, let's do the same for a Profile.   The Profiles section of ThingWorx Analytics looks for combinations of data which are highly correlated with your desired goal.   On the left, click Analytics Builder > Profiles.   Click New....   In the Profile Name field, enter simulated_profile. In the Dataset field, select simulated_dataset.   Click Submit. Wait ~30 seconds for the Profile State to change to COMPLETED.     Just like with Signals, our Profile is too good. In fact, Analytics is indicating that just s1_fb2 by itself is the primary indicator of good vs. bad grease conditions.   This is likely due to random chance. The random noise added to s1_fb2 just happened to be slightly less than the other frequency bands, so everything else was discarded.   Regardless, ThingWorx Analytics is quickly seeing through our simulated data.   Next, we'll actually create a Model using the simulated dataset.     Click here to view Part 2 of this guide  
View full tip
  Step 8: Troubleshooting   Issue                                       Resolution CSS does not seem to be applied to the Mashup. Verify your CSS is included in the runtime TWX CSS. Clear Browser cache if your CSS is not merged to the combined TWX CSS. (under debug mode: Hold refresh button->Clear Cache). TWX fails to import the extension. If the extension is already installed, but you made recent changes, you need to bump the Version number in the metadata.xml. Recent CSS changes are ignored. Clear browser cache if your CSS file has changed recently.     Step 9: Next Steps   Congratulations! You've successfully completed the Add Style to Your UI with CSS guide, and learned how to:   Create custom CSS classes using the integrated CSS editor Bind CSS classes to a Mashup and to individual Widgets Use Media queries to dynamically apply styling   Learn More   We recommend the following resources to continue your learning experience:    Capability     Guide Build Application Development Tips & Tricks Experience ThingWorx Application Development Reference   Additional Resources   If you have questions, issues, or need additional information, refer to:  Resource       Link Community Developer Community Forum Support Help Center
View full tip
    Step 9: File Transfer    To handle file transfers, create a virtual directory in the FileTransferExample Entity and in the project directory. The source code used for this example is found in com.thingworx.sdk.examples.FileTransferExample.java.   Set Up File Transfer   Right-click the project. Click New. Scroll and select Folder. Enter transfer/incoming into the text box at the bottom. Click Finish. Repeat steps 1 and 2, but create a folder called transfer/outgoing. Right-click the transfer/outgoing folder. Click New. Scroll and select File. Create a file with the name outgoing.txt. Click Finish. Once the outgoing.txt document is open, add the following text, click Save, and close the file: Hello. This is a file coming from the client application. Navigate to the FileTransferExample.java code and update the lines below with the appropriate information for your IP, port, and the admin_key Application Key’skeyId value in Composer: config.setUri("ws://127.0.0.1:80/Thingworx/WS"); config.setAppKey("ce22e9e4-2834-419c-9656-ef9f844c784c"); NOTE: Step 7 is only used for a time constraint of this guide. Best practice is to never use an Application Key for the Administrator. Provide a User with the necessary privileges and add an Application Key to that User.   FileTransferExampleHelper Methods   To support file transfers in your client application, you must use a FileTransferVirtualThing to enable the functionality and 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.   The example provided creates the FileTransferVirtualThing with 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:   All of the creations of the payloads have been moved to a helper class (FileTransferExampleHelper.java) to make the design cleaner.   The below table provides insight into some of the helper methods created to separate roles for a cleaner solution.   Method Purpose createSystemRepositoryIncomingPath Create the payload for the call to create the “incoming” directory on the SystemRepository in the ThingWorx Platform. createSystemRepositoryOutgoingPath Create the payload for the call to create the “outgoing” directory on the SystemRepository in the ThingWorx Platform. createTransferIncomingParameters Create the payload for the call to copy a file into the incoming directory on the FileTransferExample Thing in the ThingWorx Platform and the provided client application. createTransferOutgoingParameters Create the payload for the call to copy a file from the outgoing directory in the provided client application to the SystemRepository on the ThingWorx Platform.     Service Parameters   Once the connection is made, the script will call the four services. Here, we instruct the server to move the files from one repository to another.   Parameter Example Description sourceRepo “SystemRepository” The name of a FileRepository or RemoteThingWithFileTransfer Thing to transfer the file from. sourcePath “/outgoing” The path specifying the location in the file repository of the source file. sourceFile “example.txt” The name of the source file. targetRepo FileTransferExample The name of a FileRepository or RemoteThingWithFileTransfer Thing to transfer the file to. targetPath “in” The path specifying the destination location of the file. targetFile “example.txt” The name of the file at the target location. This name can differ from the sourceName parameter. timeout 15000 The amount of time to wait for the synchronous transfer to complete (seconds) before cancelling the transfer. async false If false, the service call will block for the length specified by the “timeout” parameter or until it completes.     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 copied 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.       Step 10: Troubleshooting   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: Tunneling Example    To handle file transfers, a virtual directory is created in the TunnelExample Entity and in the project directory. The source code used for this example is in com.thingworx.sdk.examples.TunnelExample.java.   To enable tunneling, create the configurations like other steps, and then either invoke ClientConfigurator.tunnelsEnabled(true), or set the tunnelsEnabled directive in your config file.   Once it connects to the server, this client binds thingName to the matching RemoteThingWithTunnels defined on the ThingWorx Platform. Once bound, the Thing can receive tunnel requests from the Platform, and facilitate tunnels to local applications.     Step 12: Next Steps    Congratulations! You've successfully completed the Java SDK Tutorial, and learned how to utilize the resources provided in the Java SDK create your own application.   The next guide in the Connect and Configure Industrial Devices and Systems learning path is C SDK Tutorial.   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 Java Edge SDK Help Center    
View full tip
    Step 6: Power Grid Example   In the Power Grid application, there are three Generator Things and three Consumers. Each Thing has a number of Properties based on its location, wattage, and its power lines provided with power. In this design, when a generator goes offline, comes back online, or one of the other power grid aspects are updated/created/deleted, the Property values are updated. The GeneratorThing class extends the VirtualThing class and based on the Generator entities in the Composer. After extending VirtualThing, there are a number of steps necessary to get going. For the GeneratorThing and SimpleThing classes, there are a number of methods for creating Properties, Events, Services, and Data Shapes for ease of use.   The constructor for the GeneratorThing takes in the type of electricity generator, name of the Thing, the description of the Thing, and the ConnectedThingClient instance used to make the connection. It then sends these values to the VirtualThing constructor as shown below. public GeneratorThing(String type, String name, String description, ConnectedThingClient client) { super(name, description, client); ...   We use the initializeFromAnnotations method to initialize all of the annotations that we will create in this class. This is done as follows and a necessary call for VirtualThings in the constructor:   initializeFromAnnotations();   Create Properties   You can create Properties in two ways. Using annotations is the recommended method, but there are times in which programmatically creating properties is the best option. For example, constructing dynamic features or allowing inline functionality would call for the coding style of Property creation. The following shows the Properties that correlate to those in the DeliveryTruck Entities in the Composer. To do this within the code, you would use a PropertyDefinition instance as shown in the SimpleThing.java property1 creation.   With Annotation @ThingworxPropertyDefinition(name="GeneratorType", description="Type of generator", baseType="STRING", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Wattage", description="Wattage produced", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Amps", description="Amps", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Voltage", description="Voltage", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="UpTime", description="Number of minutes since the generator connected online", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Status", description="Status of the generator", baseType="NUMBER", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="Location", description="Location of the generator", baseType="LOCATION", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="LastSync", description="The last time we performed a sync", baseType="DATETIME", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="ConnectedSince", description="Time where we last performed a successful connection", baseType="DATETIME", aspects={"isReadOnly:false"}),@ThingworxPropertyDefinition(name="TransmissionLines", description="An infotable of power lines", baseType="INFOTABLE", aspects={"isReadOnly:false"}) Without Annotation //Create the property definition with name, description, and baseType PropertyDefinition property1 = new PropertyDefinition(property, "Description for Property1", BaseTypes.BOOLEAN); //Create an aspect collection to hold all of the different aspects AspectCollection aspects = new AspectCollection(); //Add the dataChangeType aspect aspects.put(Aspects.ASPECT_DATACHANGETYPE, new StringPrimitive(DataChangeType.NEVER.name())); //Add the dataChangeThreshold aspect aspects.put(Aspects.ASPECT_DATACHANGETHRESHOLD, new NumberPrimitive(0.0)); //Add the cacheTime aspect aspects.put(Aspects.ASPECT_CACHETIME, new IntegerPrimitive(0)); //Add the isPersistent aspect aspects.put(Aspects.ASPECT_ISPERSISTENT, new BooleanPrimitive(false)); //Add the isReadOnly aspect aspects.put(Aspects.ASPECT_ISREADONLY, new BooleanPrimitive(false)); //Add the pushType aspect aspects.put("pushType", new StringPrimitive(DataChangeType.NEVER.name())); //Add the defaultValue aspect aspects.put(Aspects.ASPECT_DEFAULTVALUE, new BooleanPrimitive(true)); //Set the aspects of the property definition property1.setAspects(aspects); //Add the property definition to the Virtual Thing this.defineProperty(property1); Property values can either be set with defaults using the aspects setting. Nevertheless, setting a default value will affect the Property in the ThingWorx platform after binding. It will not set a local value in the client application. In this example, we make a request to the ThingWorx Composer for the current values of the generator properties using our getter methods: //Get the current values from the ThingWorx Composer wattage = getGeneratorWattage(); voltage = getGeneratorVoltage(); location = getLocation();   Create Event Definitions   As with Properties, Events can be created using annotations or code as shown in SimpleThing.java. Here we create the GeneratorOffline event that is in the Generator instances.   With Annotation   @ThingworxEventDefinitions(events = { @ThingworxEventDefinition(name="GeneratorOffline", description="The event of a generator going offline", dataShape="GeneratorShape", isInvocable=true, isPropertyEvent=false) })   Without Annotation   //Create the event definition with name and description EventDefinition event1 = new EventDefinition(event, "Description for Event1"); //Set the event data shape event1.setDataShapeName("SimpleDataShape"); //Set remote access event1.setLocalOnly(false); //Add the event definition to the Virtual Thing this.defineEvent(event1);   Create Remote Services   With remote Services, the implementation is handled by the Java application and can be called either within the application or remotely, by the Composer while a connection is established. The GetTruckReadings Service, a dummy Service used as an example of how to create a remote Service, populates an Info Table and returns that Info Table for whoever would like to use it. You can see how it is possible to define remote Services that can later be bound to Things in the Composer. A Service is defined using @ThingworxServiceDefinition annotation and its result is defined using @ThingworxServiceResult. These annotations take various parameters among including:   Name Description baseType Aspects In the second line, you can see the name of the result being set by the CommonPropertyNames field to keep development consistent with creating Things in the Composer. With Annotation @ThingworxServiceDefinition(name="OhmsLawCalculator", description="Get the watts/power (W) based on input voltage (V) and current (I)") @ThingworxServiceResult(name=CommonPropertyNames.PROP_RESULT, description="Result", baseType="NUMBER")   Without Annotation //Create the service definition with name and description ServiceDefinition service1 = new ServiceDefinition(service, "Description for Service1"); //Create the input parameter to string parameter 'name' FieldDefinitionCollection fields = new FieldDefinitionCollection(); fields.addFieldDefinition(new FieldDefinition("name", BaseTypes.STRING)); service1.setParameters(fields); //Set remote access service1.setLocalOnly(false); //Set return type service1.setResultType(new FieldDefinition(CommonPropertyNames.PROP_RESULT, BaseTypes.STRING)); //Add the service definition to the Virtual Thing this.defineService(service1); //Service1 Definition public String Service1(String name) throws Exception { String result = "Hello " + name; return result; }   Create Data Shapes   Data Shapes must be created using code as seen in GeneratorThing.java as shown below:   // Data Shape definition that is used by the generating going offline event   FieldDefinitionCollection fields = new FieldDefinitionCollection();fields.addFieldDefinition(new FieldDefinition(TYPE_FIELD, BaseTypes.STRING));fields.addFieldDefinition(new FieldDefinition(WATTAGE_FIELD, BaseTypes.STRING));fields.addFieldDefinition(new FieldDefinition(AMPS_FIELD, BaseTypes.NUMBER));fields.addFieldDefinition(new FieldDefinition(VOLTAGE_FIELD, BaseTypes.NUMBER));fields.addFieldDefinition(new FieldDefinition(UP_TIME_FIELD, BaseTypes.NUMBER));fields.addFieldDefinition(new FieldDefinition(STATUS_FIELD, BaseTypes.NUMBER));fields.addFieldDefinition(new FieldDefinition(LOCATION_FIELD, BaseTypes.LOCATION));fields.addFieldDefinition(new FieldDefinition(LAST_SYNC_FIELD, BaseTypes.DATETIME));fields.addFieldDefinition(new FieldDefinition(CONNECTED_SINCE_FIELD, BaseTypes.DATETIME));fields.addFieldDefinition(new FieldDefinition(POWER_LINES_FIELD, BaseTypes.INFOTABLE));defineDataShapeDefinition("GeneratorShape", fields); NOTE: It is possible to create a Data Shape, and then use it in a Service definition within your code as StringIndex property, StringMap Data Shape, and StringMapService Service in SimpleThing.java.     Scan Cycles   To complete the implementation of the VirtualThing class, we recommend you provide an override and implementation to the processScanRequest method. This method provides a universal method for all VirtualThing implementations. This method could be used or a new method could be created for this purpose. The processScanRequest method in VirtualThing.java does not have an implementation of its own. An implementation from DeliveryTruckThing.java can be seen below:   // The processScanRequest is called by the PowerGrid class every scan cycle @Override public void processScanRequest() throws Exception { // Execute the code for this simulation every scan this.scanDevice(); this.updateSubscribedProperties(1000); this.updateSubscribedEvents(1000); }   Bound Properties in Cycle   The scanDevice method in GeneratorThing.java performs a number of tasks from retrieving Property values to firing Events. To retrieve a Property using binding, a request is made to the client using the name of the Property. A good programming practice is to handle how these Properties are accessed and set. Note that the update method for Properties and Events must be used after queueing an Event or setting a Property value. In the example below (used within the Delivery Truck Example), getter and setter methods are used for added control. The getProperty() call is used on the VirtualThing: public Double getSpeed() { return (Double) getProperty("Speed").getValue().getValue(); } public void setSpeed() throws Exception { setProperty("Speed", this.speed); } public Location getLocation() { return (Location) getProperty("Location").getValue().getValue(); } public void setLocation() throws Exception { setProperty("Location", this.location); }     Click here to view Part 4 of this guide.
View full tip
Solution Central and Azure Active Directory Written by: Tori Firewind, IoT EDC   As we’ve said in a previous post, Solution Central (SC) is a crucial part of any mature dev ops pipeline. In its latest version (3.1.0), it manages custom solutions even more easily due to the SC API. However, this comes with a few requirements that can be a little tricky.   One of the more complex configuration pieces for using this new API involves a cloud-hosted Active Directory (AD) application within Azure AD. In order to make use of the new API, your organization’s users must exist on an Azure AD tenant that is separate from the PTC tenant. Most PTC customers are placed on this PTC-owned tenant by default, so additional configuration may be required to set up the AD instance within Azure before the SC API can be used. The type of tenant has to be Azure, of course, as that is what PTC uses: a multi-tenancy Azure infrastructure for all authentication.   In this usage, “tenant” is a cloud-hosting, infrastructure term which essentially refers to an Azure VM hosting an Active Directory server, as well as managing the many AD components that would otherwise require a lot of oversight. Users within that AD server are grouped so that only those solutions published by their own organizations are visible within Solution Central. In this way, the term “tenant” can also refer to a partition of some kind of data; a Solution Central tenant includes the users, the solutions, and is sort of like a sub-tenant of the larger PTC infrastructure. PTC uses a global Solution Central tenant for deployment of its own solutions, like DPM (Digital Performance Management), which is therefore available to every user in the PTC Azure AD tenant or a tenant which has been connected using the tutorial below.   There are good reasons to want to use your own Azure AD integrated into Solution Central that do not involve using the SC API. For one thing, it allows for direct control over the users that have access; otherwise, a ticket to PTC support is necessary every time a user needs access granted or removed. The tutorial below is a great reference for anyone using Solution Central, with steps 1-4 offering an easy guide for integrating your own Azure AD and simplifying your user management.   To use the SC API, however, there are additional steps required to create an application for retrieving an oauth token. This application needs the “solution-publisher” role or else bad request/forbidden errors will pop up. This role is automatically available in your Azure AD tenant once it is linked to the PTC AD tenant, but it does have to be manually assigned to the application, whose sole function is to request this access token for authenticating requests against the SC server.   The Azure application you need to create is essentially a plugin with permission to publish solutions against the SC API. It functions a little like a “login” in database terminology, serving the function of authenticating to an endpoint (in this case not tied to a user or any kind of identity). This application must be able to request an access token successfully and return that to the scripts which call upon it in order to perform the project creation and publication requests. The tutorial below steps you through how to create this application and request all of your solutions via the SC API.   Tutorial: Create Azure AD Application to Access SC via API Create a new tenant in Azure AD for users who will have access to the SC API Create a ticket with PTC to provide the tenant ID and begin the onboarding process Once that process completes, you will receive an email with a custom link to login to the Solution Central portal for your organization, where only your solutions exist Users will then need to be added as “Custom Global Administrators” on the SC enterprise application within Azure Portal to grant them access to login to Solution Central in a browser In order for us to be able to use the SC API, however, more work needs to be done; an application to request an oauth token for requests must be created in Azure Portal Navigate to “App Registrations” from the Azure AD page in Azure Portal and then click “New registration” Enter the application name (ours is called “gradle-plugin-tokenfetcher” in the examples shown here), and select the “single tenant” radio button Enter a URL for redirect URI and for “Select a platform” select “Web” Click “Register”, and wait for the application created notification Now we need to add permissions to see Solution Central Open the app from under “App registrations” and select the “API permissions” tab Click “Add a permission” and in the pop-up window that appears, select the “APIs my organization uses” tab, which should have PTC Solution Central listed, if this tenant has been linked to the PTC tenant per step 2 above Select “Application Permissions” and then check the “solution-publisher” role Click “Add permissions” The application now has access to Solution Central as a publisher, able to send solution publications over the API and not just via the Platform interface   The application is ready now, so we can create a request to test that it has access to SC Using Windows Powershell or something similar, create a script to make a couple of cURL requests against first the Azure AD and then the Solution Central API (attached as well): The tenant ID and the directory ID are the same value (listed on the tenant under “Overview”), and the client ID and application ID are the same as well (listed on the application, shown here), so don’t be confused by terminology The client app secret is the “Value” provided by the system when a new client secret is created under “Certificates & Secrets” (remember to copy this as soon as it is made and before clicking away, as after that, it will no longer be visible): The Solution Central app ID can be found under “App registrations”, listed within the details for the “solution-publisher” role: This access token request piece must be done before every request to the SC API, so this secret should be kept in some kind of password management tool (or a global environment variable in GitLab) so that it isn’t found anywhere in the source code If the script pings the SC API successfully, then a list of solutions will be returned
View full tip
With ThingWorx, we can already use univariate anomaly alerts (on a single sensor value). However, in many situations, the readings from an individual sensor may not tell you much about the overall issue and a multivariate anomaly detector can be more useful. This post is intended to provide an overview of the Azure Anomaly Detector and how it can be integrated with ThingWorx. The attachment contains: A document with detailed instructions about the setup; A .csv file with the multivariate timeseries dataset; A .twx file with some entities that need to be imported in ThingWorx as well as the CSVParser extension that needs to be installed; A .zip file that will need to uploaded in an Azure Blob Container at some point in the setup
View full tip
Hi everyone,   We’re back! And we’ve got exciting news about Solution Central! As tempted as I am to share the news myself, I thought it only fitting to have Janie Pascoe, Product Manager of Solution Central, share the news with you. You may remember Janie from this post on ThingWorx's OPCUA functionality or this one on what it’s like to transition from a ThingWorx developer to a ThingWorx product manager. Janie, welcome back! The floor is yours.   Janie, PM of Solution Central: Thank you so much Kaija. I wanted to bring your readers up to speed on some of the latest and greatest in Solution Central. If you haven’t logged in to the Solution Central portal in a while, I highly recommend you do so because you will immediately be notified of what’s new in the application as you can see here due to our newly added what’s new popup blurb!     But in the spirit of giving you even more detail, let me tell you a bit more about what is new in Solution Central 3.0. This release is full of more intelligence than ever before! You can now not only deploy the solutions themselves from Solution Central but deploy all of a solution’s dependencies with the single click of a button. So, instead of having to deploy each dependency separately and in a specific order, Solution Central is now smart enough to understand the dependencies and deploy them for you. We have also added enhancements to our Solution Detail panel to make it even more intuitive and easy find what you’re looking for. And when it comes to clean up activities, we have you covered. Solution Central can now forget an instance when it’s no longer needed—no more questioning whether an instance is in active use or not.   Kaya: Thanks, Janie. Exciting stuff! Readers, you can learn all about these new features and more in our Release Notes and Help Center documentation. Be sure to try out the latest functionality!   Any questions, comments, or ideas for enhancements to Solution Central can be sent directly to jpascoe@ptc.com.   Stay on the lookout for our next release!   As always, stay connected, Kaya
View full tip
We will host a live Expert Session: "Upgrade to Thingworx 9 – How to Plan / Evaluate Impacts" on January 12th 8h00 EST.   Please find below the description of the expert session and the registration link: Expert Session: Upgrade to Thingworx 9 – How to Plan / Evaluate Impacts Date and Time: January 12th 8h00 EST Duration: 1 hour Host: Ayush Tiwari - IoT Product Manager Registration Here: https://www.ptc.com/en/customer-success/expert-sessions-for-thingworx-foundation-webcasts    Description: This session will highlight the key points you should evaluate to properly plan your upgrade to Thingworx 9.   Existing Recorded sessions can be found on support portal using the keyword ‘Expert Sessions’. You can also suggest topics for upcoming sessions using this small form.   Here are some recorded sessions that might be of your interest. You can find recordings for the full library of webinars using the keyword ‘Expert Sessions’ in PTC support portal search.   Thingworx Flow Overview Flow is a powerful component of the ThingWorx platform.  This session will take the Flow discussion beyond basic applications and into more customized and complex solutions.​ This will focus on use cases, main features such as triggers, connector options, main enhancements for Thingworx 9.0 and a short demonstration   Recoding Link Top 5 items to check for Thingworx Performance Troubleshooting How to troubleshoot performance issues in a Thingworx Environment? Here we cover the top 5 investigation steps that will help you understand the source of your environment issues and allow better communication with PTC Technical Support     Recording Link
View full tip
Hi all,   Here is the recording of the expert session hosted in August 25th. For full-sized viewing, click on the YouTube link in the player controls.
View full tip
Applicable Releases: ThingWorx Navigate 1.8.0 to 1.9.0     Description:   New improvements of the ThingWorx Navigate Installer with the following agenda: What's new Load Balancer Multiple Windchill Systems Integration Runtime NSSM How to select files to download Installer installation steps Demo Questions         Additional information How to install PTC Navigate
View full tip
Applicable Releases: ThingWorx Platform 7.0 to 8.5   Description:   Introduction to Edge connectivity in Thingworx Foundation: Edge concept and definition Available edge products Why use Edge products What is Edge Microserver and Lua Script Resource What are the SDKs What are connection servers AlwaysOn and HTTP protocols ThingTemplates to connect remote devices     The session was recorded in an old ThingWorx version, but all the concepts are still applicable
View full tip
Applicable Releases: ThingWorx Platform 8.0 to 8.5; ThingWorx Navigate 1.5.0 to 8.5.0   Description:   Definition and concepts of Single Sign On (SSO), terminologies, components and architecture, as well as configuration prerequisites and high level steps to configure using PingFederation with Windchill and Navigate and main troubleshooting techniques    
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.   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.   This is the last guide in the Connect and Configure Industrial Devices and Systems Learning Path.  If you wish to return to the Learning Path, click the link.   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 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. 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 3 of this guide.   
View full tip
Applicable Releases: ThingWorx Platform 8.3 to 8.5   Description:   Installation walkthrough of ThingWorx foundation using PostgreSQL, materializing some main steps that might be difficult to read in the installation guides       Reference installation guides for each version
View full tip
This is an example of an advanced apc-metadata.xml file for use with Axeda Artisan that includes examples of how to create different data structures on the platform, including Expression Rules and System Timers. Step 1 - In the upload.xml make sure the artisan-installer is 1.2     <dependencies>         <dependency>             <groupId>com.axeda.community</groupId>             <artifactId>artisan-installer</artifactId>             <version>1.2</version>         </dependency>     </dependencies> Step 2 - <?xml version="1.0" encoding="UTF-8"?> <!--         apc-metadata.xml --> <apcmetadata>     <models>         <model>             <name>DemoModel</name>             <!--standalone or gateway-->             <type>gateway</type>             <DataItems>                 <DataItem>                     <name>PendingMessage</name>                     <!--string or digital or analog-->                     <type>string</type>                     <visible>false</visible>                     <stored>true</stored>                     <!--0 = no history,1 = Stored,2 = no storage,3 = on change-->                     <storageOption>2</storageOption>                     <readOnly>false</readOnly>                 </DataItem>                 <DataItem>                     <name>ConsumableData</name>                     <!--string or digital or analog-->                     <type>string</type>                     <visible>false</visible>                     <stored>true</stored>                     <!--0 = no history,1 = Stored,2 = no storage,3 = on change-->                     <storageOption>2</storageOption>                     <readOnly>false</readOnly>                 </DataItem>             </DataItems>         </model>     </models>     <ruleTimers>           <ruletimer>               <name>SFTP Retry</name>               <description></description>               <!--midnight gmt-->               <schedule>0 0 0 * * ?</schedule>               <rules>                   <rule>SFTP Retry</rule>               </rules>           </ruletimer>     </ruleTimers>     <expressionRules>                 <rule>             <name>SFTP Retry</name>             <description></description>             <enabled>true</enabled>             <applyToAll>true</applyToAll>             <type>SystemTimer</type>             <ifExpression><![CDATA[true]]></ifExpression>             <thenExpression>                 <![CDATA[ExecuteCustomObject("SFTPRetry")]]></thenExpression>             <elseExpression></elseExpression>             <consecutive>true</consecutive>             <models>                 <model>DemoMOdel</model>             </models>         </rule>     </expressionRules>     <customobjects>         <customobject>             <name>GetChartData</name>             <type>Action</type>             <sourcefile>GetChartData.groovy</sourcefile>             <params>                 <param name="username" description="(REQUIRED) The name of the calling user"/>             </params>         </customobject>         <customobject>             <name>GetChartData_rss</name>             <type>Action</type>             <sourcefile>GetChartData_rss.groovy</sourcefile>             <params>                 <param name="username" description="(REQUIRED) The name of the calling user"/>             </params>         </customobject>         <customobject>             <name>GetAddress</name>             <type>Action</type>             <sourcefile>GetAddress.groovy</sourcefile>             <params>                 <!--<param name="username" description="(REQUIRED) The name of the calling user"/>-->             </params>         </customobject>     </customobjects>     <applications>         <application>             <description>Chart Example</description>             <applicationId>chartexample</applicationId>             <indexFile>index.html</indexFile>             <!--<zipFile></zipFile>-->             <sourcePath>artisan-starter-html/src/main/webapp</sourcePath>         </application>     </applications> </apcmetadata>
View full tip
Applicable Releases: ThingWorx Navigate 1.6.0 to 1.7.0     Description:   How to use InfoEngine tasks to retrieve and take actions on Windchill data to use in Navigate services The following agenda is reviewed in the session: Use case introduction Create I*E task Create service Create Mashups Execute I*E Task       The concepts of this session are still valid for newer Navigate versions, but the session was recorded using old Composer
View full tip
Suppose, if you have uninstalled ThingWorx Flow successfully with appropriate steps. And, tried re-installing which is failing with below error in the flow installation logs,      " FATAL: SystemCallError: windows_service[RabbitMQ] (orchestration::rabbitmq line 120) had an error: SystemCallError: The specified service does not exist as an installed service. - OpenService: The specified service does not exist as an installed service."     This is due to the registry problem. To resolve this, need to delete the registry key. Following steps are need to be performed:    Go to Start-> Search and Run 'regedit' as an Administrator Navigate to 'Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Ericsson' Delete Ericsson key and its sub key Restart your machine Install ThingWorx Flow again and it will be successful.   Here is the article link on this subject: https://www.ptc.com/en/support/article/CS328600     Thanks, Vibhuti Angne
View full tip
Announcements