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

ThingWorx Navigate is now Windchill Navigate Learn More

IoT & Connectivity Tips

Sort by:
  Use our developer toolkit to connect Java-enabled devices and build an application.     GUIDE CONCEPT This project will introduce complex aspects of the ThingWorx Java SDK and help you to get started with development.   Following the steps in this guide, you will develop your own IoT application with the ThingWorx Java SDK.   We will teach you how to use the Java programming language to connect and build IoT applications to be used with the ThingWorx Platform.   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete all parts of this guide is 60 minutes.     YOU'LL LEARN HOW TO   Establish and manage a secure connection with a ThingWorx server, including SSL negotiation and connection maintenance Enable easy programmatic interaction with the Properties, Services, and Events that are exposed by Entities running on a ThingWorx server Create applications that can be directly used with your device running the Java programming language Basic concepts of the Java Edge SDK How to use the Java Edge API to build a real-world application How to utilize resources provided in the Edge SDK to help create your own application   Step 1: Completed Example   Download the Java_SDK_Extra_Samples.zip attached to this article and extract the contents.   In this tutorial we walk you through a real-world scenario for a power grid network. The Java_SDK_Extra_Files.zip file provided to you contains the following files and Entities as a completed version of the scenario we will cover. Please keep in mind, the Java SDK can also be utilized for Android development and general Java development.   Name Description PowerGrid Source code for an extensive example of a power grid network Delivery Truck Source code for the delivery truck application ExampleClient Source code for examples on how to do different tasks FileTransfer Source code for a file transfer application Tunneling Source code for a tunneling application SimpleThing Source code for simple connections and examples SteamSensor Source code for a steam sensor that provides configuration during runtime   Once you complete your Java environment setup and import the JavaExampleEntities.xml file into ThingWorx Composer, you will be able to utilize these Entities:   Feature Entity Type Description  Generator1  Thing  Used with the power grid edge example  Generator2  Thing  Used with the power grid edge example  Generator3  Thing  Used with the power grid edge example  Consumer1  Thing  Used with the power grid edge example  Consumer2  Thing  Used with the power grid edge example  Consumer3  Thing  Used with the power grid edge example DeliveryTruck_1 Thing Used with the delivery truck edge example DeliveryTruck_2 Thing Used with the delivery truck edge example DeliveryTruck_3 Thing Used with the delivery truck edge example FileTransferExample Thing Used with the file transfer edge example TunnelExample Thing Used with the tunnel edge example SimpleThing_1 Thing Used as a simple edge example for coding and connectivity SimpleDataShape Data Shape Used as a simple edge Data Shape example for coding and connectivity DeliveryTruckShape Data Shape Used as a Data Shape with the delivery truck edge example EdgeExample Model Tag Used as a Model Tag for tagging all entities; enables quicker searches DeliveryTable Data Table Used as a Data Table with the delivery truck edge example Default_user User User created to be used with the SDK examples PTC Organization An Organization that helps with security in edge examples Admin_key Application Key An Application Key used for the Admin Default_key Application Key An Application Key used for the Default User; this is the recommended key to use   Step 2: Environment Setup   You can use the Java SDK with any IDE of your choice. The steps below demonstrate how to use the Eclipse IDE as an example.   If you have not already done so, install a Java Development Kit (JDK) from Corretto or OpenJDK in order to compile and run Java code and download the ThingWorx Java SDK. The download will include the JARs necessary to run the SDK.   The Eclipse Java IDE is a centralized location to store the code, resources, and files utilized by this guide. Download and install the latest Eclipse Java IDE from the Eclipse website.   Create Java Project   When the Eclipse Welcome window appears, click Create a new Java Project. In the New Java Project setup wizard, enter ThingWorx Development as the project name. Java 1.8 is the supported and recommended JDK.   Click Finish.    Set Up User Library   Right click the newly created ThingWorx Development project in the Package Explorer. Expand the Build Path selection and select Add Libraries.  Click User Library. Click Next.  Click User Libraries. Click New, enter ThingWorx Java SDK as the library name. Click OK.   Set Up Javadoc   With the ThingWorx Java SDK selected, click the Add External JARs button.       In the pop-up window, navigate to the location in which you unzipped the ThingWorx Java Edge SDK. Navigate to the lib folder, select all of the JARs, then click Open. Within the ThingWorx Java SDK library, expand the thingworx-common-xxxx.jar folder and select Javadoc location. Click Edit. Select the Javadoc in archive and External file radio buttons, then click Browse. In the pop-up window, navigate to the location in which you unzipped the ThingWorx Java Edge SDK. Navigate to the lib folder, highlight the thingworx-java-sdk JavaDoc JAR File, then click Open. Click OK. Repeat steps 1-8 for the thingworx-communications-client JAR’s Javadoc location field shown in step 10. Confirm that your setup looks like this:   Click OK. Select the checkbox for the ThingWorx Java SDK library, then click Finish.   Import Sample Files   Right click the ThingWorx Development project and click Import.   In the Import wizard, type File System into the filter. Click Next.     In the pop-up window, navigate to the location in which you unzipped the ThingWorx Java Edge SDK. Navigate inside the samples folder and select the src folder.     Click OK. Select the checkbox for the src folder, then click Browse.     Type ThingWorx Development/src into the text box.   Click OK. Click Finish.     Expand the ThingWorx Development project.       Click here to view Part 2 of this guide.
View full tip
Original Post Date:     June 6, 2016 Description: This tutorial video will walk you through the installation process for the PostgreSQL-based version of the ThingWorx Platform in a Windows environment.  All required software components will be covered in this video.    
View full tip
This video is the 3 rd part of a series of 3 videos walking you through how to setup ThingWatcher for Anomaly Detection. In this video we will use Anomaly Mashup to visualize data received from my remote device.   Updated Link for access to this video:  Anomaly Detection 8.0:  Viewing Data via Anomaly Mashup:  Part 3 of 3
View full tip
IoT Streams for your end-to-end Industrial Data management with ThingWorx Since its launch with ThingWorx 10.0 in June 2025, the IoT Streams feature has been a hit!! It’s exceeded my expectations to see the creative ways it adds value to the ThingWorx ecosystem. IoT Streams utilizes Apache Kafka or Azure Event Hubs as a distributed streaming platform, serving as a robust message broker and data pipeline. It empowers industrial data management by providing access to ThingWorx contextualized data for analytics, reporting, and generative AI. It enables streaming of ThingWorx data to data lakes and cold archival storage while maintaining hot data availability for real-time insights. It also enhances the platform’s scalability and reliability with robust processing of high event volumes through a durable message broker. Working with early adopters, our services team has authored a best practices guide along with sample code to help you start with IoT Streams. The GitHub artifact located at https://github.com/PTCInc/iot_stream provides practical guidance for leveraging ThingWorx IoT Streams to: Export data from ThingWorx to external systems Implement durable queues for reliability Design scalable streaming architectures Integrate with Kafka and Azure Event Hubs In addition, with the recent ThingWorx 10.0.1 maintenance release, users can send custom JSON payloads to external messaging systems using the new WriteJSONToQueue service. Lastly, I'm also enclosing an excerpt from our ThingWorx 10.0 Webinar where you can see a demo on IoT streams and hear directly from ThingWorx and Microsoft on how it enables integration between ThingWorx and Microsoft Fabric: For full video, checkout the replay of ThingWorx 10.0 webinar here: https://www.ptc.com/en/resources/industrials/webcast/thingworx-10-launch-replay So, check it out, try IoT Streams in your projects, and share how you’re using it in the comments. For questions or support, please do not hesitate to log a technical support ticket.   Cheers, Ayush Tiwari Director Product Management
View full tip
Users of ThingWorx Analytics (TWA) may choose to create a predictive model using TWA or import a predictive model that was created using other software. When importing into or exporting out of TWA, this predictive model must be in a PMML (Predictive Model Markup Language) version 4.3+ format. This post describes how to complete the import and export processes. Exporting: The user may create a model in two main ways inside of TWA: using the Builder user interface, or by using ‘Create Job’ service that exists the Training Thing. Whichever method is used, a model Job Id is created automatically by TWA for that model. It is this model Job Id that is used to identify the model inside of TWA, regardless of what is being done with that model.   If a model is trained using Builder, the user may highlight that model, click ‘Job Details’, and then copy the Job ID. This is done as follows:   Next, the user will navigate to Browse --> Things --> …TrainingThing. This is the Training Microservice inside of TWA where all the functionality involved with training a model exists. Within the …TrainingThing, the user will execute the ‘RetrieveModel’ service under Services. When executing the service, the user will paste the model Job ID (ex. 49704f1a-7fcd-4e38-ab53-84ef46517d0a) they copied earlier, and press ‘Execute’. The resulting text can then be highlighted and copied to Notepad or some other text editor, and saved as .pmml format (ex. ‘ModelExport.pmml’).   Importing Through Results Microservice: To import a model that has been saved in PMML 4.3+ format into TWA using the Results Microservice, the user will navigate to Manage --> Repositories (ex. AnalyticsUploadStorage) --> Actions --> Upload, and choose the PMML file. The user will then navigate to Browse --> Things --> …ResultsThing. This is the Results Microservice inside of TWA where all the functionality exists related to previously trained models. Within the …ResultsThing, the user will execute the ‘UploadModel’ service under Services. Alternatively, the user can upload the model from any repository using ‘UploadModelFromRepository” service.   To create a model from the uploaded PMML inside of TWA, the user will fill out the filePath and name then execute the service. Note: This model will not show up in Builder, as that would require model validation information that is not part of the imported PMML file.   The resulting Job Id can be used to make predictions, such as by using the …PredictionThing’s BatchScore or RealtimeScore services. At this point, the uploaded model acts the same way as if the model were created inside of that TWA environment.       Importing Through Analytics Manager: To import a model that has been saved in PMML 4.3+ format into TWA using the Analytics Manager, the user will navigate to Analytics --> Analytics Manager --> Analysis Models, and click the green “New” button. Next the user will choose the provider name (or create a new one by navigating to Analytics --> Analytics Manager --> Analysis Providers). The user will also check the box to “Upload Model”, and click the grey “Choose File” button to find the PMML file. Finally, the user will click the black “Upload” button, then the green “Save” button.     At this point, the model is uploaded into ThingWorx Analytics, and the user may progress through the subsequent steps to set up “Analysis Events” and “Analysis Jobs” that will be powered by the imported model.
View full tip
ThingWorx 8.2 System Requirements ThingWorx 8.2 Helpcenter The following feature enhancements and bug fixes exist in ThingWorx 8.2.0: Due to security updates, a minimum version of Apache Tomcat 8.0.47 or 8.5.23 should be used with ThingWorx. Enhancements Platform • Included information about opting out of metrics reporting. For more information, see the ThingWorx Metrics Reporting Services Configuration section in the Platform Subsystem help topic. • The Script Log Error has been added to improve error logging for scripts. • Added support to allow mashups to be rendered using jQuery 3.x runtime. • Query service optimization. This includes improved performance for the QueryPropertyHistory and QueryPropertyNamedHistory services. Previously, a database call was made for every logged property. With this improvement, one database call is made for all logged properties, resulting in the following improvements: ▪ A ~20% decrease in memory usage for the QueryPropertyHistory and QueryNamedPropertyHistory service queries if no filters are applied (PostgreSQL and MSSQL). ▪ Decreased time to execute query (~10%) for the QueryPropertyHistory and QueryNamedPropertyHistory services. Depends on latency to the database (PostgreSQL and MSSQL). ▪ Additional decrease in memory, based on the filter supplied during the query for QueryPropertyHistory and QueryNamedPropertyHistory services. (PostgreSQL and MSSQL). If a filter is applied that reduces the record count by 50%, then there is an additional 50% decrease in memory usage on top of the other 50% described in the first point. This optimization also results in an approximate 10% decrease in memory for single property queries. The Audit Subsystem has been added. It supports the following capabilities: • Automatically add audit entries to online storage. • Search for audit entries (use the QueryAuditHistory service) stored online. • Archive online audit entries to offline storage (automatically performed daily by default). • Export audit data, using the language selected for the export. • Purge online audit data on the basis of a specified number of days for audit data to remain online and also on the specified number of rows to keep online. • Clean up archived audit data automatically, based on a configured schedule. • The security of the PASSWORD base type has been enhanced and is now encrypted. See Passwords for more information. • Added the Collection Widget, which allows you to replicate/repeat mashups and content by using infotables to dynamically supply visual content and data. Refer to the KCS article for additional information here • Additional capability has been added to New Composer. For more information, refer to the ThingWorx Community blog. • The licensing process has been improved. An activation ID is no longer required to obtain a license and a new license file is not required for minor or major release upgrades. ◦ For connected scenarios, activation IDs are no longer required in the platform-settings.json file. ◦ For disconnected scenarios, go to the enhanced PTC Support site pages, select the product, enter a Device ID, and retrieve a license. • You can enable the Application Key Authenticator when SSO is enabled by editing the sso-settings.json configuration. For more information, see Configure the sso-settings.json File. • The CSS Editor was added to Mashup Builder, which allows developers to create modern experiences with responsiveness, animations, and advanced styling and behaviors. Refer to the KCS article for additional information here. • Added support for "Store and Forward" functionality to the interface between KEPServerEX and the ThingWorx platform. KepServerEX can be configured to store updated property data to disk when disconnected from the ThingWorx platform and will send that data gracefully when the connection is re-established. • In mashups, row and column gadget sizes 1 to 8 are now available. TW-25477 Bug Fixes Platform Related JIRA • Fixed an issue with Thing Shapes when editing subscriptions twice before canceling or closing in which the second edit was not saved. TW-28718 • Fixed an issue that was causing SQL Server apparent deadlock exceptions. TW-28208 • Added useful log information for troubleshooting LDAP and Active Directory errors. TW-23873 • Fixed an issue with exception handling in DSLProcessor in which line numbers were not included in the log. TW-18042 TW-17255 • Fixed an issue in which opening/closing brackets are not highlighted if there were 100 or more lines of code in a JavaScript service. TW-12740 Mashup Builder • Service error notification messages were fixed to display on multiple lines based on line breaks in the message. TW-24738 • Fixed an issue in which a master mashup header image was not fully displayed. PSPT-3365 Extensions Related JIRA • The Google Maps JavaScript API was updated to prevent the use of the library without an api key. If you are using the Google Map extension in your application, verify that the extension's metadata.xml file is updated with the correct URL (https://maps.google.com/maps/api/js?sensor=false&key=YOUR_API_KEY). Re-zip the extension and reimport into ThingWorx after making this change.
View full tip
Underneath video walks through how to Publish a Model from Analytics Builder into Analytics Manager using the connector named TW.AnalysisServices.AnalyticsServer.AnalyticsServerConnector.
View full tip
DataShape Simply put, it represents the data in your model giving your application an in-built sense on how to represent the data in different scenarios. DataShape is defined with set of field definitions and related metadata e.g. DataType. DataShapes are must have (except for ValueStream) when creating entities that deal with data storage i.e. DataTable & Stream. For more detail on  DataShapes and the DataTypes see DataShapes in ThingWorx Help Center   Note: See ThingShape : Nuances, Tips & Tricks  for ThingShape vs DataShape   Ways to create DataShape   Via the ThingWorx Composer Navigate to ThingWorx Composer click on New > DataShape Provide a unique name to the DataShape entity DataShape creation in ThingWorx Composer Navigate to the Field Definition and add required Field Definition Defining Field for the DataShape Via a custom service in ThingWorx Navigate to an entity under which the service is to be created, e.g. Thing Switch to Services section for the Thing and click Add to create new service OOTB available service CreateDataShape can be used from the Resources > EntityService // snippet creating the infotable with the var params = { infoTableName : "InfoTable", dataShapeName : "DemoDataShape" }; // CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(DemoDataShape) var result = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params); // snippet creating the DataShape using the Infotable queried above which returns the field and the metadata on those fields // DSName used below is created as the Resources["EntityServices"].CreateDataShape({ name: DSName /* STRING */, description: "Custom created DataShape" /* STRING */, fields: result /* INFOTABLE */, tags: undefined /* TAGS */ }); Here's how it'd appear in the Service editor :   DataShape creation with JavaScript service in ThingWorx Via the ThingWorx Extension SDK   Following example snippet shows the creation and usage of the DataShape while creating custom extension with the Extension SDK    @ThingworxConfigurationTableDefinitions(tables = { @ThingworxConfigurationTableDefinition(name = "ConfigTableExample1", description = "Example 1 config table", isMultiRow = false, dataShape = @ThingworxDataShapeDefinition(fields = { @ThingworxFieldDefinition(name = "field1", description = "", baseType = "STRING"), @ThingworxFieldDefinition(name = "field2", description = "", baseType = "NUMBER") })) }) Note: Refer to the ThingShape : Nuances, Tips & Tricks for Tips & Tricks   Other related reads How are DataShape used while storing the data in ThingWorx How to pass a DataShape as parameter Can two DataShapes have the same service name if used on the same thing in ThingWorx? DataShape in ThingWorx Help Center
View full tip
As of Dec. 23, 2021, ThingWorx 9.3.0 is available for download and on Jan. 7, 2022, it will be available for Cloud Services.   What’s new in ThingWorx 9.3? Composer and Mashup Builder  Enhanced ability to find entities, code references, and project dependencies with a new Referenced by report feature. New Grid widget allows for improved visualization of row/columnar type data, with improved performance, styling, and configuration experiences.  Composer enhancements allow for faster configuration and application management in the areas of test execution and dynamic use of Master Mashups.    Analytics  New configuration parameters (binningStrategy and allowOverlap) available for profiles to tailor application of the algorithm to meet needs of domain use cases.  New option to utilize K-Fold cross validation to improve quality of predictive models created on limited data sets using industry standard technique.  Automate treatment of missing values to reduce data preparation before application of advanced analytics algorithms.    Foundation  Query performance improvements with indexing enables performance of quick “search” queries across thousands of connected assets and pre-filtering of query resultsets for better overall query performance.  Upgrade script improvements for logging, script execution and error handling which simplify the upgrade process.    Remote Access and Control  Improvements to Remote Access and Control includes Auto & Click to Launch capabilities that streamline the remote access startup process by starting the support application you need for you. New connectivity options enable user control and selection of local IP and Port addresses used in the session creation.    Software Content Management  Instructions can now be configured to execute either Synchronously or Asynchronously for a streamlined execution process. Added support for data migration of older, from the audit data table information into a format to the new audit database.    View release notes here and be sure to upgrade to 9.3!   Stay Connected, Rachel
View full tip
Create Custom Business Logic    Overview   This project will introduce you to creating your first ThingWorx Business Rules Engine.   Following the steps in this guide, you will know how to create your business rules engine and have an idea of how you might want to develop your own. We will teach you how to use your data model with Services, Events, and Subscriptions to establish a rules engine within the ThingWorx platform.   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 60 minutes.    Step 1: Completed Example   Download the attached, completed files for this tutorial: BusinessLogicEntities.xml.   The BusinessLogicEntities.xml file contains a completed example of a Business Rules Engine. Utilize this file to see a finished example and return to it as a reference if you become stuck during this guide and need some extra help or clarification. Keep in mind, this download uses the exact names for entities used in this tutorial. If you would like to import this example and also create entities on your own, change the names of the entities you create.   Step 2: Rules Engine Introduction   Before implementing a business rule engine from scratch, there are a number of questions that should first be answered. There are times in which a business rule engine is necessary, and times when the work can be down all within regular application coding.   When to Create a Rules Engine: When there are logic changes that will often occur within the application. This can be decisions on how to do billing based on the state or how machines in factories should operate based on a release. When business analysts are directly involved in the development or utilization of the application. In general, these roles are often non-technical, but being involved with the application directly will mean the need for a way to make changes. When a problem is highly complex and no obvious algorithm can be created for the solution. This often covered scenarios in which an algorithm might not be the best option, but a set of conditions will suffice.   Advantages of a Rules Engine The key reward is having an outlet to express solutions to difficult problems than can be easily verifiable. A consolidated knowledge base for how a part of a system works and a possible source of documentation. This source of information provides people with varying levels of technical skill to all have insight into a business model.   Business Logic with ThingWorx Core Platform: A centralized location for development, data management, versioning, tagging, and utilization of third party applications. The ability to create the rules engine within the ThingWorx platform and outside of ThingWorx platform. Being that the rules engine can be created outside of the ThingWorx platform, third party rules engines can be used. The ThingWorx platform provides customizable security and provided services that can decrease the time in development.     Step 3: Establish Rules   In order to design a business rules engine and establish rules before starting the development phase, you must capture requirements and designate rule characteristics.   Capture Requirements The first step to building a business rules engine is to understand the needs of the system and capture the rules necessary for success.   Brainstorm and discuss the conditions that will be covered within the rules engine Construct a precise list Identify exact rules and tie them to specific business requirements.   Each business rule and set of conditions within the business rule will need to be independent of other business rules. When there are several scenarios involved, it is best to create multiple rules – one handling each. When business rules are related to similar scenarios, the best methodology is to group the rules into categories.   Category Description Decision Rules Set of conditions regarding business choices Validation Rules Set of conditions regarding data verifications Generation Rules Set of conditions used for data object creation in the system Calculation Rules Set of conditions that handle data input utilized for computing values or assessments   Designate Rule Characteristics Characteristics for the rules include, but are not limited to: Naming conventions/identifiers Rule grouping Rule definition/description Priority Actions that take place in each rule.   After this is completed, you will be ready to tie business requirements to business rules, and those directly to creating your business rules engine within the platform.   Rules Translation to ThingWorx There are different methods for how the one to one connections can be made between rules and ThingWorx. The simplified method below shows one way that all of this can be done within the ThingWorx platform:   Characteristic  ThingWorx Aspect Rule name/identifier Service Name Ruleset  Thing/ThingTemplate Rule definition  Service Implementation Rule conditions Service Implementation Rule actions Service Implementation Data management DataTables/Streams   Much of the rule implementation is handled by ThingWorx Services using JavaScript. This allows for direct access to data, other provided Services, and a central location for all information pertaining to a set of rules. The design provided above also allows for easier testing and security management.   Step 4: Scenario Business Rule Engine    An important aspect to think about before implementing your business rules engine, is how the Service implementation will flow.   Will you have a singular entry path for the entire rules engine? Or will you have several entries based on what is being requested of it? Will you have create only Services to handle each path? Or will you create Events and Subscriptions (Triggers and Listeners) in addition to Services to split the workload?   Based on how you answer those questions, dictates how you will need to break up your implementation. The business rules for the delivery truck scenario are below. Think about how you would break down this implementation.   High Level Flow 1 Customer makes an order with a Company (Merchant). 1.A Customer to Merchant order information is created. 2 The Merchant creates an order with our delivery company, PTCDelivers. 2.A Merchant order information is populated. 2.B Merchant sets delivery speed requested. 2.C Merchant sets customer information for the delivery. 3 The package is added to a vehicle owned by PTCDelivers. 4 The vehicle makes the delivery to the merchant's customer.   Lower Level: Vehicles 1 Package is loaded onto vehicle 1.i Based on the speed selected, add to a truck or plane. 1.ii Ground speed option is a truck. 1.iii Air and Expedited speed options are based on planes usage and trucks when needed. 2 Delivery system handles the deliveries of packages 3 Delivery system finds the best vehicle option for delivery 4 An airplane or truck can be fitted with a limited number of packages.   Lower Level: Delivery 1 Delivery speed is set by the customer and passed on to PTCDelivers. 2 Delivery pricing is set based on a simple formula of (Speed Multiplier * Weight) + $1 (Flat Fee). 2.i Ground arrives in 7 days. The ground speed multiplier is $2. 2.ii Air arrives in 4 days. The air speed multiplier is $8. 2.iii Expedited arrives in 1 day. The expedited speed multiplier is $16. 3 Deliveries can be prioritized based on a number of outside variables. 4 Deliveries can be prioritized based on a number of outside variables. 5 Bulk rate pricing can be implemented.   How would you implement this logic and add in your own business logic for added profits? Logic such as finding the appropriate vehicle to make a delivery can be handled by regular Services. Bulk rates, prioritizing merchants and packages, delivery pricing, and how orders are handled would fall under Business Logic. The MerchantThingTemplate Thing contains a DataChange Subscription for it's list of orders. This Subscription triggers an Event in the PTCDelivers Thing.   The PTCDelivers Thing contains an Event for new orders coming in and a Subscription for adding orders and merchants to their respective DataTables. This Subscription can be seen as the entry point for this scenario. Nevertheless, you can create a follow-up Service to handle your business logic. We have created the PTCDeliversBusinessLogic to house your business rules engine.   Step 5: Scenario Data Model Breakdown   This guide will not go into detail of the data model of the application, but here is a high level view of the roles played within the application.   Thing Shapes ClientThingShape Shape used to represent the various types of clients the business faces (merchants/customers). VehicleThingShape Shape used to represent different forms of transportation throughout the system.   Templates PlaneThingTemplate Template used to construct all representations of a delivery plane. TruckThingTemplate Template used to construct all representations of a delivery truck. MerchantThingTemplate Template used to construct all representations of a merchant where goods are purchased from. CustomerThingTemplate Template used to construct all representations of a customer who purchases goods.   Things/Systems PTCDeliversBusinessLogic This Thing will hold a majority of the business rule implementation and convenience services. PTCDelivers A Thing that will provide helper functions in the application.   DataShapes PackageDeliveryDataShape DataShape used with the package delivery event. Will provide necessary information about deliveries. PackageDataShape DataShape used for processing a package. OrderDataShape DataShape used for processing customer orders. MerchantOrderDataShape DataShape used for processing merchant orders. MerchantDataShape DataShape used for tracking merchants.   DataTables OrdersDatabase DataTable used to store all orders made with customers. MerchantDatabase DataTable used to store all information for merchants.     Step 6: Next Steps   Congratulations! You've successfully completed the Create Custom Business Logic guide, and learned how to: Create business logic for IoT with resources provided in the ThingWorx platform Utilize the ThingWorx Edge SDK platforms with a pre-established business rule engine   We hope you found this guide useful.    The next guide in the Design and Implement Data Models to Enable Predictive Analytics learning path is Implement Services, Events, and Subscriptions.     
View full tip
ThingWorx and Azure IoT Hub Benchmark This Azure IoT Hub Reference Benchmark showcases the capabilities of ThingWorx and Microsoft Azure IoT Hub, a cloud-hosted solution backend that facilitates secure and reliable communication between an IoT application such as ThingWorx and the devices it manages. By making use of this third party tool, remote monitoring with ThingWorx has never been simpler.   In this benchmark, PTC verifies the reliability and scalability of ingesting data through the Azure IoT Hub into the Azure IoT Hub Connector(s) and ThingWorx Foundation. The preliminary version of this document focuses primarily on how the Azure IoT Hub’s capabilities modify and/or enhance the data ingestion and device management capabilities of ThingWorx.   Find the benchmark document attached here, and stay tuned for more reference benchmarks to come!
View full tip
  Create compelling, modern application user interfaces in ThingWorx with the latest enhancements to our Mashup visualization platform - Collection and Custom CSS.   In this webinar with IoT application designer Gabriel Bucur, we'll show how the new Collection widget makes it easy to replicate visual content in your UI for menu systems, dashboards, tables, and more. You'll learn about several of the 60+ configuration properties available for collections, many of which offer input/output bindings for dynamic flexibility.   Gabriel will also demonstrate the styling and UX power of the latest feature in the Next Gen Composer, which allows you to write classes and CSS for your Mashups, masters, and widgets.   Watch the recording above, and download this sample Mashup containing all the data and entities shared in the video.   Q&A   We didn’t have time to get to all of the questions during the live webcast, but we’ve answered them here on our blog. Have any additional questions? Please leave us a comment.   WILL PTC CONTINUE SUPPORT FOR THE REPEATER WIDGET IN THINGWORX 8.2, OR WILL IT BE REMOVED? The Repeater Widget will not removed. However, due to limited performance in various browsers, switching to the Collection is highly recommended.   WHAT’S THE DIFFERENCE BETWEEN REPEATER AND COLLECTION, AND ARE THERE PROS AND CONS FOR EACH WIDGET? The Collection is an advanced widget that allows you to contain a series of repeated Mashups within a collection. Its functionality is similar to the Repeater Widget, but contains more properties that provide additional options and better performance, especially when handling large amounts of data.   IS IT POSSIBLE TO ADD A DRAG AND DROP ACTION TO LISTS OR REPEATERS, E.G. DRAGGING AN ELEMENT FROM ONE CONTAINER TO ANOTHER? Drag and drop functionality is not available in the Collection Widget at this time. It is, however, in consideration for future ThingWorx releases.   IN THE EVENT I HAVE MORE THAN ONE MASHUP (FOR EXAMPLE, MASHUP A AND MASHUP B), CAN I BIND DIFFERENT PROPERTIES TO THE SAME MASHUP PARAMETER ACCORDING TO THE MASHUP NAME? The MashupName row goes to the MashupNameField in the collection, where you’ll  have a dropdown after you populate it with the InfoTable that contains the MashupName. You can put all the bindings there, even if you don't use them in all the Mashups. For example: {"valueA":"MashupA","valueB":"MashupB"}   IS IT POSSIBLE TO ORDER SECTIONS HORIZONTALLY IN THE COLLECTION? Sections can only be ordered vertically at this time.   WHAT IS THE DIFFERENCE BETWEEN GLOBAL PROPERTIES AND SESSION VALUES? Global Properties are only available within the Collection. These properties offer a way to control Things from other widgets with which the Collection is displaying.   IF THERE ARE MULTIPLE COLLECTIONS, DO THEY SHARE THE SAME SET OF GLOBALPARAMETERS? No. If you defined a Boolean on your Collection, when you drag the Boolean output from a checkbox on the Collection you will see that you can bind it to that defined Boolean in the GlobalParameters.   WHEN USING CUSTOM CSS, DO YOU HAVE TO DEFINE STYLING FOR EACH ELEMENT, OR CAN YOU CREATE A STYLE THING WITH CSS? Widgets differ in functionality, so the same class might not apply to the same widget. However, if you define a styling in CSS for a button, for example, you can apply that class on any button you want.   DOES CUSTOM CSS ALWAYS OVERRIDE THE WIDGET STYLES? Yes. That is the essential purpose of custom CSS integration – to rewrite styles.   IF YOU HAVE TWO CONFLICTING STYLES – ONE IN CSS AND THE OTHER IN A STYLE DEFINITION – WHICH ONE TAKES PRECEDENCE? CSS will typically rewrite the ThingWorx styles; however, it depends on the specificity of the CSS target definition. For example: “.button-element" will be overwritten by ".default-button .button-element". Visit https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity for more details regarding this topic.   CAN I RESIZE MY WIDGETS DURING RUNTIME? The size of the widget is determined by the CSS, and how it renders in ThingWorx. While you can bind different sizing classes to the CustomClass property of the widget, resizing with your mouse is not available at Runtime.
View full tip
Original Post Date:            June 6, 2016   Description: This is a video tutorial on creating a Stream, adding a Data Shape with properties, and writing values to the Stream.    
View full tip
When I tried to set String property values with Chinese letters by using C SDK, I could see only broken characters in Thingworx. The cause of the problem is simple and it's encoding. In order to solve this problem, you need to convert encoding to UTF-8 in your C code. I used 'libiconv' library to do it. This guide is for Win32 version. If you want to make a library for other platforms such as Linux, you can create or get a library for your own by googling. How to Get the Source Code of libiconv At the moment, the most recent version of libiconv is 1.15. You can download the source code of libiconv from here. How to Build I used MS Visual Studio 2012, but the explanation can be applied to the earlier versions of MS Visual Studio and express editions. Step 1. Download the most recent version of libiconv and unzip the file. Step 2. Make a new Win32 Project. Let's say "libiconv" as the project name. Check to create directory for solution. Choose DLL as the application type and check Empty Project for additional options. Click the button "Finish" to generate the new project. Step 3. Copy files from the folders of libiconv to project folders. To build "libiconv", you need to compile three files "localcharset.c", "relocatable.c" and "iconv.c". That's the key! Copy three files "relocatable.h", "relocatable.c" and "iconv.c" in the folder "...\libiconv-1.15\lib\" to the project folder "...\libiconv\libiconv\". Copy "...\libiconv-1.15\libcharset\lib\localcharset.c" to the project folder "...\libiconv\libiconv\". Copy "...\libiconv-1.15\libcharset\include\localcharset.h.build.in" to the project folder "...\libiconv\libiconv\" and then, rename the copied "localcharset.h.build.in" to "localcharset.h". Copy "...\libiconv-1.15\windows\libiconv.rc" to the project folder "...\libiconv\libiconv\". Make folder "include" under the project folder "...\libiconv\". Copy "...\libiconv-1.15\include\iconv.h.build.in" to the project include folder "...\libiconv\include" and then, rename the copied "iconv.h.build.in" to "iconv.h". Copy "...\libiconv-1.15\config.h.in" to the project include folder "...\libiconv\include" and then, rename the copied "config.h.in" to "config.h". Copy all the header files (*.h) and definition files (*.def) in the folder "...\libiconv-1.15\lib" to the project include folder "...\libiconv\include". Step 4. Add existing items. Execute "project > Add Existing items..." at the main menu to add existing items to the project. Step 5. Project Settings. You can make 64-bit platform through configuration manager in order to generate libiconv.dll for 64-bit system. You can also make two other configurations "ReleaseStatic" and "DebugStatic" in order to generate libiconvStatic.lib as a static link library. At the project properties, change Output Directory as "$(SolutionDir)$(Configuration)_$(Platform)\" and Intermediate Directory as "$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\". Change Include Directories as "..\include;$(IncludePath)": You have to add "BUILDING_LIBICONV" and "BUILDING_LIBCHARSET" to Peprocessor Definitions of all Platforms and of all configurations. You'd better set Runtime Library to "Multi-threaded" when building dynamic link library libiconv.dll. Then, the dependency on VC Runtime library can be controlled by the applications that will be built and dynamically linked with libiconv.dll because libiconv.dll does not need VC Runtime library but only the application that uses libiconv.dll may or may not need VC Runtime library. However, when building the static link library libiconvStatic.lib, you can choose Runtime Library option for libiconvStatic.lib depending on the application that uses libiconvStatic.lib. You have to change Precompiled Header option to "Not Using Precompiled Headers". Step 6. Tweak the source code. libiconv.rc Open libiconv.rc with text editor or the source code editor of Visual Studio IDE by double-clicking libiconv.rc in the Solution explorer and insert some code at line 4 as follows: /////////////    ADD    ///////////// #define PACKAGE_VERSION_MAJOR 1 #define PACKAGE_VERSION_MINOR 14 #define PACKAGE_VERSION_SUBMINOR 0 #define PACKAGE_VERSION_STRING "1.14" ///////////////////////////////////// You may be asked to change Line endings to "Windows (CR LF)". Then, let it do so. It will be more convenient for you if you mainly use Windows. localcharset.c Open localcharset.c and delete or comment the lines 80 - 83 as follows: //////////////////  DELETE //////////////// ///* Get LIBDIR.  */ //#ifndef LIBDIR //# include "configmake.h" //#endif /////////////////////////////////////////// iconv.c Open iconv.c and delete or comment the lines 250 - 252 and add three lines there as follows: ///////////////////////// DELETE /////////////////////// //size_t iconv (iconv_t icd, //              ICONV_CONST char* * inbuf, size_t *inbytesleft, //              char* * outbuf, size_t *outbytesleft) /////////////////////////   ADD   ////////////////////// size_t iconv (iconv_t icd,               const char* * inbuf, size_t *inbytesleft,               char* * outbuf, size_t *outbytesleft) //////////////////////////////////////////////////////// localcharset.h Open localcharset.h and delete or comment the lines 21 - 25 and add 7 lines there as follows: /////////////////////////   DELETE  //////////////////////// //#if @HAVE_VISIBILITY@ && BUILDING_LIBCHARSET //#define LIBCHARSET_DLL_EXPORTED __attribute__((__visibility__("default"))) //#else //#define LIBCHARSET_DLL_EXPORTED //#endif /////////////////////////    ADD    ////////////////////// #ifdef BUILDING_LIBCHARSET #define LIBCHARSET_DLL_EXPORTED __declspec(dllexport) #elif USING_STATIC_LIBICONV #define LIBCHARSET_DLL_EXPORTED #else #define LIBCHARSET_DLL_EXPORTED __declspec(dllimport) #endif //////////////////////////////////////////////////////////////////// config.h Open config.h in the project include folder "...\libiconv\include" and delete or comment the lines 29 - 30 as follows: ///////////////////////// DELETE /////////////////////// ///* Define as good substitute value for EILSEQ. */ //#undef EILSEQ //////////////////////////////////////////////////////// Otherwise you can redefine EILSEQ as good substitute value. iconv.h Open iconv.h in the project include folder "...\libiconv\include" and delete or comment the line 175 and add 1 line as follows: /////////////////////////  DELETE  /////////////////////// //#if @HAVE_WCHAR_T@ /////////////////////////    ADD   ////////////////////// #if HAVE_WCHAR_T //////////////////////////////////////////////////////////////////////////////// Delete or comment the line 128 and add 1 line as follows: /////////////////////////  DELETE  /////////////////////// //#if @USE_MBSTATE_T@ /////////////////////////   ADD   ////////////////////// #if USE_MBSTATE_T //////////////////////////////////////////////////////////////////////////////// Delete or comment the lines 107-108 and add 2 lines as follows: /////////////////////////  DELETE  /////////////////////// //#if @USE_MBSTATE_T@ //#if @BROKEN_WCHAR_H@ /////////////////////////  ADD  ////////////////////// #if USE_MBSTATE_T #if BROKEN_WCHAR_H //////////////////////////////////////////////////////////////////////////////// Delete or comment the line 89 and add 2 lines as follows: /////////////////////////  DELETE /////////////////////// //extern LIBICONV_DLL_EXPORTED size_t iconv (iconv_t cd, @ICONV_CONST@ char* * inbuf, //size_t *inbytesleft, char* * outbuf, size_t *outbytesleft); /////////////////////////    ADD   ////////////////////// extern LIBICONV_DLL_EXPORTED size_t iconv (iconv_t cd, const char* * inbuf,   size_t *inbytesleft, char* * outbuf, size_t *outbytesleft); //////////////////////////////////////////////////////////////////////////////// Delete or comment the lines 25 - 30 and add 8 lines as follows: /////////////////////////  DELETE /////////////////////// //#if @HAVE_VISIBILITY@ && BUILDING_LIBICONV //#define LIBICONV_DLL_EXPORTED __attribute__((__visibility__("default"))) //#else //#define LIBICONV_DLL_EXPORTED //#endif //extern LIBICONV_DLL_EXPORTED @DLL_VARIABLE@ int _libiconv_version; /* Likewise */ /////////////////////////    ADD   ////////////////////// #if BUILDING_LIBICONV #define LIBICONV_DLL_EXPORTED __declspec(dllexport) #elif USING_STATIC_LIBICONV #define LIBICONV_DLL_EXPORTED #else #define LIBICONV_DLL_EXPORTED __declspec(dllimport) #endif extern LIBICONV_DLL_EXPORTED int _libiconv_version; /* Likewise */ //////////////////////////////////////////////////////////////////////////////// How to Use When you use newly built libiconv, the only header file that you need is iconv.h. You will need to link either the import library libiconv.lib or the static library libiconvStatic.lib in your project property or write the code in one of your source file as follows: #pragma comment (lib, "libiconv.lib") or #pragma comment (lib, "libiconvStatic.lib") In the source of the application that uses this library either libiconv.dll or libiconvStatic.lib, if you don't define anything but only include iconv.h, your application will use libiconv.dll while it will use libiconvStatic.lib if you define USING_STATIC_LIBICONV before you include iconv.h in your application as follows: //#define USING_STATIC_LIBICONV #include <iconv.h> And in C SDK code, I used a "SteamSensorWithFileTransferAndTunneling" sample code and added codes in the "dataCollectionTask" function as below. void dataCollectionTask(DATETIME now, void * params) {   iconv_t ic;   char* in_buf = "Hi, 文健英";   char *to_chrset = "UTF-8";   char *from_chrset = "EUC-KR";   size_t in_size = strlen(in_buf);   size_t  out_size = sizeof(wchar_t) * in_size * 4;   char* out_buf = malloc(out_size);   // Caution: iconv's inbuf, outbuf are double pointers, so need to define separate pointers and pass addresses.   char* in_ptr = in_buf;   char* out_ptr = out_buf;   size_t out_buf_left;   size_t result;   memset(out_buf, 0x00, out_size);      ic = iconv_open(to_chrset, from_chrset);   if (ic == (iconv_t) -1)   {         printf("Not supported code \n");         exit(1);   }   printf("input len = %d, %s\n", in_size, in_buf);   out_buf_left = out_size;   iconv(ic, &in_ptr, &in_size, &out_ptr, &out_buf_left);   //printf("input len = %d, output len=%d %s\n", in_size, out_size - out_buf_left, out_buf);   iconv_close(ic);   /* 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);   properties.BigGiantString = out_buf; // Set values for String property   /* 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(); }
View full tip
We will host a live Expert Session: "Top 5 Thingworx environment monitoring best practices" on March 25th, 10h00 EST.   Please find below the description of the expert session and the registration link.   Expert Session: Top 5 Thingworx environment monitoring best practices Date and Time: March 25th, 10h00 EST Duration: 1 hour Host: Tori Firewind, Tim Atwood and Dave Bernbeck from Enterprise Deployment Center - Enterprise Deployment Center Registration Here: https://www.ptc.com/en/resources/iiot/webcast/top-5-thingworx-monitoring-best-practices    In this session, we will be reviewing the main monitoring practices to keep a heathy environment and discuss the main issues from the audience. Bring your questions!.   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 Active Active Clustering This session will cover the main aspects of the High Availability Clustering feature launched with the ThingWorx 9.0 release.   Recoding Link Upgrade to Thingworx 9 – How to Plan / Evaluate Impacts This session highlights the key points you should evaluate to properly plan your upgrade to Thingworx 9. Recording 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
This small tutorial enables you to manage payload decoding for Adeunis Devices within ThingWorx Composer in less than 10 minutes.  Adeunis Devices communicates on LPWAN networks (LoRaWAN / Sigfox) covering sectors such as smart building, smart industry and smart city. The encoding is also possible but it will be covered in another article.   1. Get Adeunis Codec Adeunis is providing a codec enabling payload encoding and decoding.  Download here the resource file containing the codec.  Unzip the file and edit "script.txt" with your favorite text editor. Copy all text contained in the file.   2.  Create AdeunisCodec Thing Create a Thing called "AdeunisCodec" based on the GenericThing Template.   3. Create a service called "Decode" Create a Decode Service with the following setup: Inputs: type (String), payload (String) Output as JSON Past the previously copied "script.txt" content Save   4. Correct a couple of Warnings Remove all "var codec;" occurences except first one at line 1191.  Remove semi columns at lines 985,1088, 1096 and 1172   5. Remove the following section The codec relies on implementing functions on JavaScript prototypes which is not supported by ThingWorx Rhino JavaScript Engine. See the following documentation section, here.    Remove from line 1109 to 1157.   The following classes overrides will be removed: Uint8Array.prototype.readUInt16BE Uint8Array.prototype.readInt16BE Uint8Array.prototype.readUInt8 Uint8Array.prototype.readUInt32BE Uint8Array.prototype.writeUInt16BE Uint8Array.prototype.writeUInt8 Uint8Array.prototype.writeUInt32BE 6. Add new implementations of the removed functions The functions are adapted from a JavaScript framework which contains resources that helps dealing with binary data, here. Insert the  following section at the top of the "Decode" script.         function readInt16BE (payload,offset) { checkOffset(offset, 2, payload.length); var val = payload[offset + 1] | (payload[offset] << 8); return (val & 0x8000) ? val | 0xFFFF0000 : val; } function readUInt32BE (payload,offset) { checkOffset(offset, 4, payload.length); return (payload[offset] * 0x1000000) + ((payload[offset + 1] << 16) | (payload[offset + 2] << | payload[offset + 3]); } function readUInt16BE (payload,offset) { checkOffset(offset, 2, payload.length); return (payload[offset] << | payload[offset + 1]; } function readUInt8 (payload,offset) { checkOffset(offset, 1, payload.length); return payload[offset]; } function writeUInt16BE (payload,value, offset) { value = +value; offset = offset >>> 0; checkInt(payload, value, offset, 2, 0xffff, 0); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); payload[offset + 1] = value; } else objectWriteUInt16(payload, value, offset, false); return offset + 2; } function writeUInt8 (payload,value, offset) { value = +value; offset = offset >>> 0; checkInt(payload, value, offset, 1, 0xff, 0); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); payload[offset] = value; return offset + 1; } function writeUInt32BE (payload,value, offset) { value = +value; offset = offset >>> 0; checkInt(payload, value, offset, 4, 0xffffffff, 0); if (Buffer.TYPED_ARRAY_SUPPORT) { payload[offset] = (value >>> 24); payload[offset + 1] = (value >>> 16); payload[offset + 2] = (value >>> 8); payload[offset + 3] = value; } else objectWriteUInt32(payload, value, offset, false); return offset + 4; } function objectWriteUInt16 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffff + value + 1; for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> (littleEndian ? i : 1 - i) * 8; } } function objectWriteUInt32 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffffffff + value + 1; for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * & 0xff; } }     7. Add the following function to support previous inserted functions     function checkOffset (offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new Error ('offset is not uint'); if (offset + ext > length) throw new Error ('Trying to access beyond buffer length'); }     8. Add the following function for casting String to Bytes     function splitInBytes(data) { var bytes = []; var bytesAsString = ''; for (var i = 0, j = 0; i < data.length; i += 2, j++) { bytes[j] = parseInt(data.substr(i, 2), 16); bytesAsString += bytes[j] + ' '; } return bytes; }     9. Remap function calls to newly inserted functions Use the built-in script editor replace feature for the following, see below:   Within the service script perform a Replace for each of the following lines. Search Replace by payload.readInt16BE( readInt16BE(payload, payload.readUInt32BE( readUInt32BE(payload, payload.readUInt16BE( readUInt16BE(payload, payload.readUInt8( readUInt8(payload, payload.writeUInt16BE( writeUInt16BE(payload, payload.writeUInt8( writeUInt8(payload, payload.writeUInt32BE( writeUInt32BE(payload,   10. At the Bottom update the following Replace : decoder.setDeviceType("temp"); By : decoder.setDeviceType(type);   11. Insert the following at the bottom var result = Decoder(splitInBytes(payload), 0);   12. Save Service and Thing   13. Create a test Service for Adeunis Temp Device Within "AdeunisCodec" Thing Create a new service called "test_decode_temp" with Output as String Insert the following code:      // result: STRING var result = me.Decode({type: "temp" /* STRING */,payload: "43400100F40200F1" /* STRING */});     Save & Execute  The expected result is:     {"temperatures":[{"unit":"°C","name":"probe 1","id":0,"value":24.4},{"unit":"°C","name":"probe 2","id":0,"value":24.1}],"type":"0x43 Temperature data","status":{"frameCounter":2,"lowBattery":false,"hardwareError":false,"probe1Alarm":false,"configurationDone":false,"probe2Alarm":false}}       Please visit the Decoder test section of Adeunis website to see the reference for the Temp device test case, here.   Spoiler (Highlight to read) The resources has been tested on ThingWorx 8.5 and with the latest and greatest ThingWorx 9...   If you are more interested in the result than in the implementation process then import the attached "Things_AdeunisCodec.xml" 😉  The resources has been tested on ThingWorx 8.5 and with the latest and greatest ThingWorx 9...  If you are more interested in the result than in the implementation process then import the attached "Things_AdeunisCodec.xml"    
View full tip
There's a reason why many "Hello World" tutorials begin with writing to the logging tool.  Developers live in the console, inserting breakpoints and watching variables while debugging.  Especially with interconnected, complex systems, logging becomes crucial to saving developer hours and shipping on time. What this tutorial covers This tutorial introduces the three principal methods of monitoring the status of assets and the output of operations on an Axeda instance. Audit Logs Custom Object Log Reports The Audit Log You can filter the Audit Log by date range or by category. A list of the Audit Categories is available in the Help documentation at http://<<yourhost>>.axeda.com/help/en/audit_log_categories_for_filtering... You can write to the Audit Log from an Expression Rule or from a Custom Object. Writing to the Audit Log from an Expression Rule Use the Audit Action to write to the Audit Log: Audit("data-management", "The temperature " + DataItem.temp.value + "was reported at " + FormatDate(Now(), "yyyy/MM/dd hh:mm:ss")) You can insert values from the Variables or Functions list by using the plus operator as a string concatenator. Writing to the Audit Log from a Custom Object import com.axeda.common.sdk.id.Identifier import com.axeda.drm.sdk.Context import com.axeda.drm.sdk.audit.AuditCategory import com.axeda.drm.sdk.audit.AuditMessage auditMessage(Context.getSDKContext(), "data_management", "Thread started timestamp has ended.", context.device.id) private def auditMessage(Context CONTEXT, String category, String message, Identifier assetId) {     AuditCategory auditCategory = AuditCategory.getByString(category) ?: AuditCategory.DATA_MANAGEMENT     if (assetId == null) {         new AuditMessage(CONTEXT, "com.axeda.drm.rules.functions.AuditLogAction", auditCategory, [message]).store()     } else {         new AuditMessage(CONTEXT, "com.axeda.drm.rules.functions.AuditLogAction",    auditCategory, [message], assetId).store()     } }     In either case, a message written in the context of an Asset will be displayed on the Asset Dashboard (assuming the Audit module is enabled for the Asset Dashboard in the Model Preferences). The Custom Object Log The Configuration (6.1-6.5)/Manage(6.6+) tab provides access to the Custom Objects log when they are selected from the View sub-menu: This links allows you to open or save a zip archive of text files called customobject.logX where X is a digit that indicates that the log has rolled over into the next file (ie, customobject.log1).  The most current is customobject.log without a digit.  These files contain logging information in chronological order, identified by Custom Object name.  The log contains full stack traces of exceptions, as well as text written to the log. ERROR 2013-06-20 18:26:02,613 [sstreBinaryReturn,ajp-10.16.70.164-8009-6] Exception occurred in sstreBinaryReturn.groovy: java.lang.NullPointerException     at com.axeda.platform.sdk.v1.services.extobject.ExtendedObject.getPropertyByName(ExtendedObject.java:276)     at com.axeda.platform.sdk.v1.services.extobject.ExtendedObject$getPropertyByName.call(Unknown Source)    The Logger object in Custom Objects is a custom class ScriptoDebuggerLogger that is injected into the script and does not need to be explicitly imported. The following attributes are available for the Logger object: logger.info() logger.debug() logger.error()   All objects can be converted to a String by using the dump() function. logger.info(context.device.dump()) Additionally, a Javascript utility can be used with all SDK v2 domain objects and some SDK v1 domain objects to get a JSON pretty-print string of their attributes. import net.sf.json.JSONArray logger.info(JSONArray.fromObject(context.device).toString(2)) // Outputs: [{   "buildVersion": "",   "condition":  {     "detail": "",     "id": "3",     "label": "",     "restUrl": "",     "systemId": "3"   },   "customer":  {     "detail": "",     "id": "2",     "label": "Default Organization",     "restUrl": "",     "systemId": "2"   },   "dateRegistered":  {     "date": 31,     "day": 4,     "hours": 18,     "minutes": 39,     "month": 0,     "seconds": 31,     "time": 1359657571070,     "timezoneOffset": 0,     "year": 113   },   "description": "",   "detail": "mwc_location_1",   "details": null,   "gateways": [],   "id": "12345",   "label": "",   "location":  {     "detail": "Default Organization",     "id": "2",     "label": "Default Location",     "restUrl": "",     "systemId": "2"   },   "model":  {     "detail": "mwc_location",     "id": "4321",     "label": "standalone",     "restUrl": "",     "systemId": "4321"   },   "name": "mwc_location_1",   "pingRate": 10000,   "properties": [],   "restUrl": "",   "serialNumber": "mwc_location_1",   "sharedKey": [],   "systemId": "12345",   "timeZone": "America/New_York" }] ​Custom object logs may be retrieved by navigating to the Configuration (6.1-6.5)/Manage(6.6+) tab and selecting Custom Objects from the View sub-menu. Click the "Log" button at the bottom of the table and save, then view customobject.log in a text editor. Reports Reports provide a summary of data about the state of objects on the Axeda Platform.  Report titles are generally indicative of what they're reporting, such as Missing Devices Report, Auditing Report, Users Report. A separate license is needed in order to use the Reports feature.  New report types can only be created by a Reports administrator. To run a report, click Run from the Reports Tab. You can manage Reports from the Administration tab. These three tools together offer a full view of the state of domain objects on the Axeda Platform.  Make sure to take advantage of them while troubleshooting assets and applications.
View full tip
Original Post Date:            September 30, 2016   Description: This tutorial video will walk you through the installation process for the PostgreSQL-based version of the ThingWorx Platform (7.2) in a RHEL environment.  All required software components will be covered in this video.    
View full tip
Previously Installing & Connecting C SDK to Federated ThingWorx with VNC Tunneling to the Edge device Installing and configuring Web Socket Tunnel Extension on ThingWorx Platform Overview     Using the C SDK Edge client configuration we did earlier, we'll now create above illustrated setup. In this C SDK Client we'll push the data to ThingWorx Publisher with servername : TW802Neo to ThingWorx Subscriber servername : TW81. Notice that the SteamSensor2 on the pulisher server is the one binding to the C SDK client and the FederatedSteamThing on subscriber is only getting data from the SteamSensor2. Let's crack on!   Content   Configure ThingWorx to publish Configure ThingWorx to subscribe Publish entities from Publisher to the Subscriber Create Mashup to view data published to the subscriber Pre-requisite Minimum requirement is to have two ThingWorx servers running. Note that both ThingWorx systems can be publisher & subscriber at the same time.   Configure ThingWorx Publisher   Configuring Federation Subsystem   1. Navigate to ThingWorx Composer > Subsystems > Federation Subsystems and configure the following highlighted sections   Essentially its required to configure the Server Identification, i.e. My Server name (FQDN / IP) , My Server Description (optional) Federation subscribers this server publishes to, i.e. all the server you want to publish to from this server. Refer to the Federation Subsystem doc in the Help Center to check detail description on each configurable parameter.   2. Save the federation subsystem   Configuring a Thing to be published   1. Navigate back to the Composer home page and select the entity which you'd like to publish 2. In this case I'm using SteamSensor2 which is created to connect to the C SDK client 3. To publish edit the entity and click on Publish checkbox, like so 4. Save the entity   Configure ThingWorx Subscriber     Configuring Federation Subsystem   1. Navigate to ThingWorx Composer > Subsystems > Federation Subsystems and configure the following highlighted sections   Essentially its required to configure the Server Identification, i.e. My Server name (FQDN / IP) , My Server Description (optional) Refer to help center doc on Federation Subsystems should you need more detail on the configurable parameter If you only want to use this server as a subscriber of entities from the publishing ThingWorx Server, in that case you don't have to Configure the section Federation subscribers this server publishes to, I've configured here anyway to show that both servers can work as publishers and subscribers   2. Save the federation subsystem   Configuring a Thing to subscribe to a published Thing 1. Subscribing to an entity is fairly straight forward, I'll demonstrate by utilizing the C SDK client which is currently pushing values to my remote thing called SteamSensor2 on server https://tw802neo:443/Thingworx 2. I have already Published the StreamSensor2, see above section Configuring a Thing to be published 3. Create a Thing called FederatedStreamThing with RemoteThingWithTunnels as ThingTemplate, 4. Browser for the Identifier and select the required entity to which binding must be done, like so   5. Navigate to the Properties section for the entity, click Manage Bindings to search for the remote properties like so for adding them to this thing:     6. Save the entity and then we can see the values that were pushed from the client C SDK     7. Finally, we can also quickly see the values pulled via a Mashup created in the subscriber ThingWorx , below a is a simple mashup with grid widget pulling values using QueryPropertyHistory service  
View full tip
This example is to achieve to update objects in Windchill thru extensions. It is really hard to find a resource for Windchill extension's services to take an advantage of them. So, I wrote a simple example to update objects in Windchill from Thingworx.   There are three data shapes needed to do this. One is "PTC.PLM.WindchillPartUfids" which has only "value" field (String) in it and another is "PTC.PLM.WindchillPartCheckedOutDS" which has a "ufid" field (String). Last one is "PTC.PLM.WindchillPartPropertyDS" which has a "ufid" field (String) and fields for "attributes". For an instance of the last data shape, there might be three fields as "ufid", "partPrice" and "quantity" to update parts. In this example, this data shape has two fields which are "ufid" and "almProjectId".   In this example, this needs two input parameters. One is ufid (String) and almProjectId (String). If you need to have multiple objects to update at once, you can use InfoTable type as an "ufid" input parameter instead of String type.   Note that this is an example code and need to handle exceptions if needed.     // To var params = {     infoTableName : "InfoTable",     dataShapeName : "PTC.PLM.WindchillPartUfids" };   // CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(PTC.PLM.WindchillPartUfids) var ufids = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);   // PTC.PLM.WindchillPartUfids entry object var newValue = new Object(); newValue.value = ufid; // STRING   ufids.AddRow(newValue);   // Check out var params = {     ufids: ufids /* INFOTABLE */,     comment: undefined /* STRING */,     dataShape: "PTC.PLM.WindchillPartCheckedOutDS" /* DATASHAPENAME */ };   // checkedOutObjs: INFOTABLE dataShape: "undefined" var checkedOutObjsFromService = me.CheckOut(params);   var params = {     infoTableName : "InfoTable",     dataShapeName : "PTC.PLM.WindchillPartUfids" };   // CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(PTC.PLM.WindchillPartUfids) var checkedOutObjs = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);   try {     var tableLength = checkedOutObjsFromService.rows.length;       for (var x = 0; x < tableLength; x++) {         var row = checkedOutObjsFromService.rows;               // PTC.PLM.WindchillPartUfids entry object         var checkedOutObj = new Object();         checkedOutObj.value = row.ufid.substring(0,row.ufid.lastIndexOf(":")); // STRING               //logger.warn("UFID : " + checkedOutObj.value);         checkedOutObjs.AddRow(checkedOutObj);           /* Update Objects in Windchill */         var params = {             infoTableName : "InfoTable",             dataShapeName : "PTC.PLM.WindchillPartPropertyDS"         };           // CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(PTC.ALM.WindchillPartPropertyDS)         var wcInfoTable = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);           // PTC.ALM.WindchillPartPropertyDS entry object         var newEntry = new Object();         newEntry.ufid = checkedOutObj.value; // STRING         newEntry.almProjectId = almProjectId; // STRING           wcInfoTable.AddRow(newEntry);           var params = {             objects: wcInfoTable /* INFOTABLE */,             modification: "REPLACE" /* STRING */,             dataShape: "PTC.PLM.WindchillPartCheckedOutDS" /* DATASHAPENAME */         };           // result: INFOTABLE dataShape: "undefined"         var result = me.Update(params);     }   } catch(err) {     logger.warn("ERROR Catched");     var params = {         ufids: ufids /* INFOTABLE */,         dataShape: "PTC.PLM.WindchillPartCheckedOutDS" /* DATASHAPENAME */     };       // result: INFOTABLE dataShape: "undefined"     var result = me.CancelCheckOut(params);  }   var params = {     ufids: checkedOutObjs /* INFOTABLE */,     comment: undefined /* STRING */,     dataShape: "PTC.PLM.WindchillPartCheckedOutDS" /* DATASHAPENAME */ };   // result: INFOTABLE dataShape: "undefined" var result = me.CheckIn(params);
View full tip
    Configure streaming asset properties for SPC monitoring.   Guide Concept   Note: This guide is intended only as a starting point and is not a fully developed or supported solution. This accelerator has been developed using ThingWorx 8.5 and should not be used with any previous versions of the software.   This project introduces you to configuring Properties from your connected streaming assets for Statistical Process Control (SPC) monitoring.   Following the steps in this guide, you will learn how multiple connected assets and their Properties can be displayed in a hierarchy tree.   You will then configure these Properties using predetermined set points, and upper and lower control points for the assets.   Finally, you will learn to navigate the monitoring of the Properties.   We introduce some of the basic building blocks of an SPC accelerator, including important Things and Mashups. You will also use ThingWorx Timers to simulate streaming data.     You'll learn how to   Configure multiple properties for SPC monitoring Identify abnormalities in streaming property values   NOTE: The estimated time to complete this guide is 30 minutes     Step 1: Import SPC Accelerator   Before exploring Statistical Process Control (SCP) within ThingWorx Foundation, you must first import some Entities via the top-right Import / Export button.   Download and unzip PTC_StatisticalCalculations_PJ.zip and PTC_SPC_PJ.zip. These two files each contain a ThingWorx project of a similar name. Import PTC_StatisticalCalculations_PJ.twx first. Import PTC_SPC_PJ.twx once the other import has completed. Explore the imported entities.   Each of the projects contain multiple entities of various types. The most important entities you will use in this guide are as follows:    Entity Name                                   Description Motor_Pump1 Timer to simulate streaming data Motor_Blower1 Timer to simulate streaming data PTC.SPC.ConfigurationHelper Thing that manages the accelerator PTC.SPC.Configuration_MU Mashup for configuring SPC properties PTC.SPC.Monitoring_MU Mashup for monitoring SPC properties   Step 2: Configure Properties for SPC monitoring   You may configure SPC monitoring for multiple production lines, connected assets on those lines, and time-series Properties on those assets using the SPC accelerator.   This is done by viewing the PTC.SPC.Configuration_MU Mashup.   Follow these steps to configure an SPC Property.   Create a new production line   In the Enter New Production Line Name text field, type Line100. Click Add New Line.   Now you will see the new production line added to the Asset Hierarchy tree along the left. All production lines you’ve created (as well as their assets and the assets’ Properties) will be shown here.   In the lower-right, the SPC Property Configuration area has disappeared because the item selected in the Asset Hierarchy tree is the new line; only assets within lines can have streaming Properties.   Add a streaming asset to Line100   Within the Select Asset Thing entity picker, type Motor_Blower1. Click Add Asset for Line.   This asset has Properties that are streaming into ThingWorx. Multiple assets can be added to the same production line by selecting the line from the Asset Hierarchy tree and following the steps above.   If you select the new asset from the Asset Hierarchy tree, you will see that the list of Properties Eligible for SPC Monitor is shown in the SPC Property Configuration area. All Properties have the same default configuration associated with them.   Configure a property for SPC Monitoring   Below is a brief description of each of the configuration parameters:    Parameter           Description Sample Size Number of consecutive property values to average together. For example, a Sample Size of 5 will tell the accelerator to group every 5 property values together and calculate their average value. XBar Points Number of the most recent sample aggregations to display in the SPC Monitoring Mashup. This also affects SPC calculations. Capability Points Number of the most recent sample aggregations to use when populating the Capability Histogram in the SPC Monitoring Mashup. Set Point Value determined to be the set point for that particular property on the asset. Lower Design Spec Value determined to be the lower design spec for that particular property on the asset. This is used for capability calculations. Upper Design Spec Value determined to be the upper design spec for that particular property on the asset. This is used for capability calculations.   Select Pressure1 from the list of eligible properties. Enter the following values:  Properties                      Values Sample Size 5 Xbar Points 30 Capability Points 60 Set Point 73 Lower Design Spec 68 Uppder Design Spec 78   3, Select Xbar-R Chart. 4. Click Add or Update SPC Monitoring. 5. Pressure1 is added to the Asset Hierarchy tree underneath the Motor_Blower1 asset. 6. If you select this Property, you can modify the configuration and save it by clicking Add or Update SPC Monitoring.   Configure assets and Properties   Follow these steps using the following parameters:                                     Line Asset  Property  Sample Size Xbar Point Capability Points Set Points Lower Design Spec Upper Design Spec Chart Type 100 Motor_Blower1 Pressure1 5 30 60 73 68 78 Xbar-R 100 Motor_Blower1 Pressure2 5 30 60 78 68 89 Xbar-R 100 Motor_Blower1 Temperature1 5 30 60 50 44 56 Xbar-s 100 Motor_Blower1 Temperature2 5 30 60 85 73 97 Xbar-s 100 Motor_Pump1 Vibration10 5 30 60 150 108 190 Xbar-s 100 Motor_Pump1 Vibration11 8 60 100 200 168 220 Xbar-s 100 Motor_Pump1 Pressure100 5 30 60 100 84 118 Xbar-R 100 Motor_Pump1 Pressure200 5 30 60 90 84 97 Xbar-R   As you add assets to Line100 and configure their Properties, you will see the Asset Hierarchy tree grow. If you need to remove an asset or its associated Properties from the Asset Hierarchy tree, you may select that item, and click Remove Selected. For any item you remove, its child-items will also be removed.   Click here to view Part 2 of this guide.
View full tip
Announcements