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:
Timers and Schedulers can also be created and configured programmatically via custom services. The following service, which can be created on any Thing, will create a new Timer using the following Inputs:         // create new Thing var params = { name: ThingName /* STRING */, description: undefined /* STRING */, thingTemplateName: "Timer" /* THINGTEMPLATENAME */, tags: undefined /* TAGS */ }; Resources["EntityServices"].CreateThing(params); // read initial configuration // result: INFOTABLE var configtable = Things[ThingName].GetConfigurationTable({tableName: "Settings"}); // update configuration with service parameters configtable.updateRate = updateRate configtable.runAsUser = user // set new configuration table var params = { configurationTable: configtable /* INFOTABLE */, persistent: true /* BOOLEAN */, tableName: "Settings" /* STRING */ }; Things[ThingName].SetConfigurationTable(params);   This code is an example which could also be used to create a new Scheduler. The configuration table for a Timer has the following attributes: updateRate enabled runAsUser The configuration table for a Scheduler has the following attributes: schedule enabled runAsUser  
View full tip
Check out this new framework to achieving digital manufacturing success. Learn about the top 3 areas teams need to consider!    Identify a unified end goal Align it with the most impactful use cases Formulate a lasting strategy that resonates their long-term vision Discover More! 
View full tip
Original Post Date:      June 6, 2016   Description: This is a video tutorial on creating an InfoTable through a service, creating and adding a Data Shape adding rows to the Infotable through a service, adding rows to an InfoTable property and querying the InfoTable.    
View full tip
In this blog we will have a look at the installation of the Thingworx Analytics Builder extension. This is used as guideline but make sure to check the Help Center for your release as steps do vary with versions. The installation has been divided in 3 parts: Introduction and import of the extension into Thingworx Platform Video Link : 1568 Configuration of the extension Note: For release 8.1, the Settings menu differs from previous versions, seeWhat's New in ThingWorx Analytics Builder 8.1 between times 00:12 sec to 00:40 sec for up to date menu selection. Video Link : 1572 Installation of the UploadThing module Note: this step no longer applies as of ThingWorx Analytics 8.1 Video Link : 1573 Useful links: PTC Download page for Thingworx Analytics PTC Reference Document page for Thingworx Analytics How to copy files from Windows to Linux ?
View full tip
  Hello everyone,   If you’re like me, you’re always looking for the optimal or most efficient way to do something. Today, I’ll share a quick trick and two tips to help you develop your awesome IoT solutions with ThingWorx.   #1. Trick: Finding Dependency References We are targeting a new “Where Used” Composer feature in an upcoming release of the platform to help you find your references of bindings, properties, mashups, and services. In the meantime, did you know you can get some of that information yourself today with a quick service call?   As of ThingWorx 8.5, a new service is present on Project entities; the service crawls the contents of your project and highlights the full external dependency list to help you find references. On any Project Entity, ListExternalDependencies() shows output like this in 9.0:  ListExternalDependencies() output   For each entity (“A”) in the project, the service calls out any entities (“B”) that it is referencing and the referenced dependency’s extension package if present. It will only find external dependencies to the project and will not currently list dependencies within the project. Notice also in the infotable output, the last column, “where used,” even lists the type of reference (e.g. coded in JavaScript, Mashup Data, Resource, Property binding, etc.). Pretty handy!   Code reference from “Where Used” service output   Click this link for additional help content that explains the service output and usage. Again, it only searches for entity references outside of your current project scope. Also, this service will stop crawling the dependency hierarchy when it finds items in a project, since its current purpose is packaging.  Consider if you have Thing T1 in Project P1, which uses ThingTemplate TT2 and it’s not in a Project. TT2, in turn, uses ThingShape TS3 which is also not in a Project.  Calling ListExternalDependencies()  on Project P1 will find both TT2 and TS3. If, however, we then put TT2 in a Project P2, then call the List() service on Project P1, the scan will stop at TT2 and NOT identify TS3.  The reason for this is that the service assumes that when you package P2, it will find the orphan TS3.     We know this doesn’t cover all “where used” type use cases, so there is still a planned feature to really complete this concept on the platform. But even in the 8.5 or 9.0 releases, if you wanted to see entity references (inside and outside of its project) for a single Thing A, you could quickly assign Thing A to a new project and run the ListExternalDependencies() service to find all of its references and then assign Thing A back to its original project once you’ve found what you are looking for. Moving entities into projects just for searching is not something I would recommend doing often, but it can work in a pinch!   #2. Tip: JavaScript looping When iterating through data from infotables, use a .forEach() loop! Consider these four code options and their average performance on the Rhino engine:  Infotable looping performance   Very clearly, the .forEach() syntax is the most performant and, in my opinion, the cleanest to read. Try it out in your app! We plan to update our help documentation with more of these ThingWorx JavaScript best practices in 9.1. We also plan to provide some updates to our Code Snippets features in an upcoming Composer release so we can recommend these good practices right from the start.   #3. Tip: Code optimizations As with many performance bottlenecks, it is those pesky loops that can really amplify degradation. Here are two ThingWorx patterns for your consideration:   Wrong Way:   In this block of code, we setup the property names we are looking for, and then loop through to make a logger message. While creating each logger message, we are making an API call for querying all things for a Thing named me.name and executing a service call GetMetadataAsJSON() on that Thing which walks the hierarchy to build a JSON representation of itself. In this trivial example, we are making these same API 2 calls for each item in the propertyNames list, though the Thing reference and JSON definitions are never changing. Pretty expensive.   Correct Way:   Notice in this example, we are not only declaring the propertyNames outside of the loop, but also the propertyDefinitions. This will significantly improve performance and reduce the number of API calls and round trips to the application server. Again, this is a trivial example, but can pay off in larger and more complex code areas.   If you like these quick tips, check out more best practices here! Got a tip of your own? Have a question on how to tackle something? As always, just Ask Kaya!   Stay connected! Kaya
View full tip
Fresh look at getting started with ThingWorx in a relevant context that outlines the DEVOPS needed to kick-start your programming.     For full-sized viewing, click on the YouTube link in the player controls. Visit the Online Success Guide to access our Expert Session videos at any time as well as additional information about ThingWorx training and services.
View full tip
Super simple widget that embeds the HTML5 audio tag, allowing MP3 files to be played and/or triggers by another mashup event.
View full tip
Continuing our series of Troubleshooting ThingWorx Analytics installations, in this IoT Tech Tip we will cover two items have been appearing for many users.   Error 1069 Encountered with Native Windows Installation of ThingWorx Analytics 8.2   In some instances, when a user successfully installs ThingWorx Analytics (TWAS) to a Windows Server operating system, they will encounter an error where TWAS will report an Error 1069: The Service did not start due to logon failure.   This can occur with any individual Service that is created by the installation, the following fix should work in addressing the issue.   Primary Reason This Happens:   This error can be encountered when the user provides incorrect credentials for associating the Services to an account during installation. In TWAS 8.2, there is a utility that will enable to the user to change the associated user on the Services. It is important the user provides the password for the User Account on Windows, and not the user/password combination for ThingWorx Foundation Platform Server.   Steps to Fix Issue   Solution 1:   Open a Command Prompt as Administrator, via Start Menu à Run à type CMD. Then right click on cmd.exe and Run As Administrator.   In the elevated command prompt, change your directory to the ThingWorxAnalyticsServer/bin directory, for example in the default installation path would be: cd C:\Program Files (x86)/ThingWorxAnalyticsServer/bin Then execute the changeServiceUserAccount.bat <username>, for example: changeServiceUserAccount.bat user1   You will be prompted to change the password for the user.   Solution 2:   If Solution 1 does not resolve the issue, alternately you can manually change the Log On properties for each of the services. The changeServiceUserAccount.bat would do this via script, but on occasion this may work. Open the Control Panel and navigate to Services, for example: Control Panel à All Control Panel Items à Administrative Tools   You will have to right click each individual service and go to Properties à Log On tab and enter the account name and password for the local account. Note: Local System account will not resolve this issue.   This issue was resolved in the ThingWorx Analytics Server 8.3 release, where all Services are associated with the Network Service account.     More information can be found in this Knowledge Article   Uploading of a Dataset hangs or does not complete in ThingWorx Analytics 8.3   On occasion, after a fresh installation of ThingWorx Analytics Server 8.3 on a Windows Server operating system, a dataset will not complete its upload. Typically no error message is displayed, and the upload wizard UI will just hang on the upload progress after:   Creating copy of Configuration File... Submitting Create Dataset request... Creating copy of Data File...   Primary Reason This Happens:   This is caused by twas-zookeeper service being stuck in a PAUSED state. This means that in the post installation, twas-zookeeper did not start.   Steps to Fix Issue   You will have to double check that the JAVA_HOME variable was defined as a System Variable. In the ThingWorx Analytics Installation guide, pages 12-14 outline the steps required as pre-requisites. You can change this in Control Panel > System > Advanced Settings > Environment Variables, and ass a new variable named JAVA_HOME under System Variables. The value location should be the location of your deployment of JAVA software.   Typically this is located in C:\Program Files\Java\<jre or jdk>_<version number>     More information can be found in this Knowledge Article
View full tip
Overview Time-series predictive models generated by ThingWorx Analytics Server in Analytics Manager will have additional columns in their dataShape generated by ThingPredictor. These columns are known as “transformation fields” and are used for internal processing but are not necessary for inclusion in the DataShape.  So there is no need to worry about mapping all these additional fields since it will be handled internally by ThingPredictor.  There is one addition step that the user must take which is detailed below. Step to Import: Edit the DataShape generated by ThingPredictor to match the format of the data that was provided during the model training process. In other words, remove all the transformation fields from the DataShape.
View full tip
I had just finished writing an integration test that needed to update a Thing on a ThingWorx server using only classes in the Java JDK with as few dependencies as possible and before I moved on, I though I would blog about this example since it makes a great starting point for posting data to ThingWorx. ThingWorx has a Java SDK which uses the HTTP Websockets protocol and you can download it from our online at the ThingWorx IoT Marketplace​ that offers great performance and far more capabilities than this example. If you are looking, however for the simplest, minimum dependency example of delivering data to ThingWorx, this is it. This examples uses the REST interface to your ThingWorx server. It requires only classes already found in your JDK (JDK 7) and optionally includes the JSON Simple jar. References to this jar can be removed if you want to create your property update JSON object yourself. Below is the Java Class. package com.thingworx.rest; import org.json.simple.JSONObject; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; /** * Author: bill.reichardt@thingworx.com * Date: 4/22/16 */ public class SimpleThingworxRestPropertyUpdater {    static {    //Disable All SSL Security Testing (Not for production!)      try {       disableSSLCertificateChecking();      } catch (Exception e) {       e.printStackTrace();      }      HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){        public boolean verify(String hostname, SSLSession session) {return true;}      });   }    public static void main(String[] args) {      // like http://localhost:8080 or https://localhost:443      String serverUrl = args[0];      // Generate one of these from the composer under Application Keys      String appKey = args[1];      String thingName = args[2];      // You don't have to use the Simple JSON class, just pass a JSON string to restUpdateProperties()      // This Thing has three properties, a (NUMBER), b (STRING) and c (BOOLEAN)      JSONObject properties = new JSONObject();      properties.put("a", new Integer(100));      properties.put("b", "My New String Value");      properties.put("c", true);      String payload= properties.toJSONString();      try {        int response = restUpdateProperties(serverUrl, appKey, thingName, payload);        System.out.println("Response Status="+response);      } catch (Exception e) {        e.printStackTrace();      }   }    public static int restUpdateProperties(String serverUrl, String appKey, String thingName, String payload) throws IOException {     String httpUrlString = serverUrl + "/Thingworx/Things/"+thingName+"/Properties/*";     System.out.println("Performing HTTP PUT request to "+httpUrlString);     System.out.println("Payload is "+payload);     URL url = new URL(httpUrlString);     HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();     httpURLConnection.setUseCaches(false);     httpURLConnection.setDoOutput(true);     httpURLConnection.setRequestMethod("PUT");     httpURLConnection.setRequestProperty ("Content-Type", "application/json");     httpURLConnection.setRequestProperty ("appKey",appKey);     OutputStreamWriter out = new OutputStreamWriter(httpURLConnection.getOutputStream());     out.write(payload);     out.close();     httpURLConnection.getInputStream();     return httpURLConnection.getResponseCode();   }    /**   * Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to   * aid testing on a local box, not for use on production.   */    private static void disableSSLCertificateChecking() throws KeyManagementException, NoSuchAlgorithmException {   TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {      public X509Certificate[] getAcceptedIssuers() {        return null;      }      public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}      public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}      } };      SSLContext sc = SSLContext.getInstance("TLS");      sc.init(null, trustAllCerts, new java.security.SecureRandom());      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());   } } When run, it prints out what the request body should look like in JSON: Performing HTTP PUT request to https://localhost:443/Thingworx/Things/SimpleThing/Properties/* Payload is  {"a":100,"b":"My New String Value","c":true} Response Status=200 I have attached the full Gradle project that builds and runs this example class as a zip file to this article. When you download it, if you have Java JDK 7 already installed an on your path, you can run the example with the command: On Linux or OSX ./gradlew simplerest Windows gradlew.bat simplerest Don't forget to edit the build.gradle file to use your server's URL and application key. You will also find the Thing used in this example in the entities folder of this project and you can import it on your server to test it out. It is a Thing that is based on GenericThing and has three properties, a (NUMBER), b (STRING) and c (BOOLEAN).
View full tip
ThingWorx 7.4 covers the following areas of the product portfolio:  ThingWorx Analytics, ThingWorx Utilities and ThingWorx Foundation which includes Core, Connection Server and Edge capabilities. Key Functional Highlights Highlights of the release include: Source Integration: Improved integration framework making it easy to connect with external systems, including a standard Windchill connector, to retrieve data on demand. Industrial Connectivity: New Industrial Gateway and Discover navigation tool simplifying the mapping of tags to properties, including performance enhancements for data updates. Edge/CSDK: Build process improvements, Subscribed Property Manager (SPM) enhancements, asynchronous service requests and TLS updates to increase developer productivity, improve application performance and strengthen security. AWS IoT Connector: The latest version 1.2 of the Connector allows customers to more fully leverage their investment in AWS IoT. It features improved deployment automation via CloudFormation and automatic extension installation, ThingWorx Edge JavaScript SDK for use with the Connector with support for properties, services and events, and just-in-time certificate registrations. Contextualize Next Generation Composer: Re-imagined Composer using modern browser concepts to improve developer efficiency including enhanced functionality, updated user interface and optimized workflows. Engage These features will be available at the end of March 2017. Advanced Grid: New grid widget with improved design, context menu, multi-column sorting, global search and many more common grid-related features. Tree Grid: New tree-grid widget with same features as advanced grid plus ability to pre-load tree levels, dynamically load child data and auto expand all nodes to build more powerful mashups. Administer & Manage MS SQL Server: New persistence provider for model and run-time data providing customers an alternative to PostgreSQL. Security: ThingWorx worked with industry standard security scanning and auditing tools to identify and correct all non-trivial, and many trivial, vulnerabilities to ensure secure software best practices. Licensing: Link ThingWorx to PTC systems of record to manage user entitlement and provide usage information and auditing capability critical to TWX, PTC and its partners.  Documentation ThingWorx 7.4 Reference Documents ThingWorx Core 7.4 Release Notes ThingWorx Core Help Center ThingWorx Edge SDKs and WebSocket-based Edge MicroServer Help Center ThingWorx Connection Services Help Center ThingWorx Utilities Help Center Additional information ThingWorx eSupport Portal ThingWorx Developer Portal ThingWorx Marketplace Download ThingWorx Platform – Select Release 7.4 ThingWorx Edge C SDK 1.4 – Select Most Recent Datecode, C-SDK-1-4-0 ThingWorx AWS IoT Connector 1.2 – Select Release 7.4 ThingWorx Utilities – Select Release 7.4
View full tip
Please open your ApplicationLog located in ThingworxStorage/logs and inspect for errors. Something like the following might be observed: **********LICENSING ERROR ANALYSIS 2017-03-31 16:29:19.591+0300 [L: ERROR] [O: ] [I: ] [U: SuperUser] [S: ] [T: localhost-startStop-1] C:\WINDOWS\Sun\Java\bin is listed as a java.library.path but it does not exist 2017-04-12 13:51:53.515+0200 [L: ERROR] [O: c.t.s.s.l.LicensingSubsystem] [I: ] [U: SuperUser] [S: ] [T: localhost-startStop-1] Failed to load FlxCore library. Ensure it's in PATH (Windows) or LD_LIBRARY_PATH(other platforms) or set with the VM arg, -Djava.library.path. Error message : com.flexnet.licensing.DllEntryPoint.entry([B) Typically, if the license file has been downloaded and placed correcrtly, according to the 7.4 installation guide, the error in the log will specify where the file was found. If the license path was specified per the installation guide in the tomcat java path, you may try to clear it from the Tomcat java settings and keep these parameters: -Dserver -Dd64 -XX:+UseNUMA -XX:+UseConcMarkSweepGC -Dfile.encoding=UTF-8 And then set up the license path in the environment variable path: Go to explorer, right click on "my computer" -> Properties -> Advanced settings -> Environment variables -> edit "PATH", add ; and then path to your tomcat extensions folder, “ ;<path to extensions folder of tomcat> “ or, for example ";C:\ptc\Thingworx\webapps\Thingworx\WEB-INF\extensions"
View full tip
By Tim Atwood and Dave Bernbeck, Edited by Tori Firewind Adapted from the March 2021 Expert Session Produced by the IoT Enterprise Deployment Center The primary purpose of monitoring is to determine when your application may be exhausting the available resources. Knowledge of the infrastructure limits help establish these monitoring boundaries, determining straightforward thresholds that indicate an app has gone too far. The four main areas to monitor in this way are CPU, Memory, Networking, and Disk.   For the CPU, we want to know how many cores are available to the application and potentially what the temperature is for each or other indicators of overtaxation. For Memory, we want to know how much RAM is available for the application. For Networking, we want to know the network throughput, the available bandwidth, and how capable the network cards are in general. For Disk, we keep track of the read and write rates of the disks used by the application as well as how much space remains on those.   There are several major infrastructure categories which reflect common modes of operation for ThingWorx applications. One is Bare Metal, which relies upon the traditional use of hardware to connect directly between operating system and hardware, with no intermediary. Limits of the hardware in this case can be found in manufacturing specifications, within the operating system settings, and listed somewhere within the IT department normally. The IT team is a great resource for obtaining these limits in general, also keeping track of such things in VMware and virtualized infrastructure models.   VMware is an intermediary between the operating system and the hardware, and often its limits are determined based on the sizing of the application and set by the IT team when the infrastructure is established. These can often be resized as needed, and the IT team will be well aware of the limits here, often monitoring some of the performance themselves already. This is especially so if Cloud Providers are used, given that these are scaled up virtualizations which are configured in easy-to-use cloud portals. These two infrastructure models can also be resized as needed.   Lastly Containers can be used to designate operating system resources as needed, in a much more specific way that better supports the sharing of resources across multiple systems. Here the limits are defined in configuration files or charts that define the container.   The difficulties here center around learning what the limits are, especially in the case of network and disk usage. Network bandwidth can fluctuate, and increased latency and network congestion can occur at random times for seemingly no reason. Most monitoring scenarios can therefore make due with collecting network send and receive rates, as well as disk read and write rates, performed on the server.   Cloud Providers like Azure provide VM and disk sizing options that allow you to select exactly what you need, but for network throughput or network IO, the choices are not as varied. Network IO tends to increase with the size of the VM, proportional to the number of CPU cores and the amount of Memory, so this may mean that a VM has to be oversized for the user load, for the bulk of the application, in order to accommodate a large or noisy edge fleet. The next few slides list the operating metrics and common thresholds used for each. We often use these thresholds in our own simulations here at PTC, but note that each use case is different, and each situation should be analyzed individually before determining set limits of performance.   Generally, you will want to monitor: % utilization of all CPU cores, leaving plenty of room for spikes in  activity; total and used memory, ensuring total memory remains constant throughout and used memory remains below a reasonable percentage of the total, which for smaller systems (16 GB and lower) means leaving around 20% Memory for the OS, and for larger systems, usually around 3-4 GB.    For disks, the read and write rates to ensure there is ample free space for spikes and to avoid any situation that might result in system down time;  and for networking, the send and receive rates which should be below 70% or so, again to leave room for spikes.   In any monitoring situation, high consistent utilization  should trigger concern and an investigation into  what’s happening. Were new assets added? Has any recent change caused regression or other issues?    Any resent changes should be inspected and the infrastructure sizing should be considered as well. For ThingWorx specific monitoring, we look at max queue sizes, entries performed, pool sizes, alerts, submitted task counts, and anything that might indicate some kind of data loss. We want the queues to be consistently cleared out to reduce the risk of losing data in the case of an interruption, and to ensure there is no reason for resource use to build up and cause issues over time. In order for a monitoring set-up to be truly helpful, it needs to make certain information easily accessible to administrative users of the application. Any metrics that are applicable to performance needs to be processed and recorded in a location that can be accessed quickly and easily from wherever the admins are. They should quickly and easily know the health of the application from a glance, without needing to drill down a lot to be made aware of issues. Likewise, the alerts that happen should be  meaningful, with minimal false alarms, and it is best if this is configurable by the admins from within the application via some sort of rules engine (see the DGIS guide, soon to be released in version 9.1). The  monitoring tool should also be able to save the system history and export it for further analysis, all in the name of reducing future downtime and creating a stable, enterprise system.     This dashboard (above) is a good example of how to  rollup a number of performance criteria into health indicators for various aspects of the application. Here there is a Green-Yellow-Red color-coding system for issues like web requests taking longer than 30s, 3 minutes, or more to respond.   Grafana is another application used for monitoring internally by our team. The easy dashboard creation feature and built-in chart modes make this tool  super easy to get started with, and certainly easy to refer to from a central location over time. Setting this up is helpful for load testing and making ready an application, but it is also beneficial for continued monitoring post-go-live, and hence why it is a worthy investment. Our team usually builds a link based on the start and end time of tests for each simulation performed, with all of the various servers being monitored by one Grafana server, one reference point.   Consider using PTC Performance Advisor to help monitor these kinds of things more easily (also called DynaTrace). When most administrators think of monitoring, they think of reading and reacting to dashboards, alerts, and reports. Rarely does the idea of benchmarking come to mind as a monitoring activity, and yet, having successful benchmarks of system performance can be a crucial part of knowing if an application is functioning as expected before there are major issues. Benchmarks also look at the response time of the server and can better enable  tracking of actual end user experience. The best  option is to automate such tests using JMeter or other applications, producing a daily snapshot of user performance that can anticipate future issues and create a more reliable experience for end users over time.   Another tool to make use of is JMeter, which has the option to build custom reports. JMeter is good for simulating the user load, which often makes up most of the server load of a ThingWorx application, especially considering that ingestion is typically optimized independently and given the most thought. The most unexpected issues tend to pop up within the application itself, after the project has gone live.   Shown here (right) is an example benchmark from a Windchill application, one which is published by PTC to facilitate comparison between optimized test systems and real life performance. Likewise, DynaTrace is depicted here, showing an automated baseline (using Smart URL Detection) on Response Time (Median and 90th percentile) as well as Failure Rate. We can also look at Throughput and compare it with the expected value range based on historical throughput data. Monitoring typically increases system performance  and availability, but its other advantage is to provide faster, more effective troubleshooting. Establish a systematic process or checklist to step through when problems occur, something that is organized to be done quickly, but still takes the time to find and fix the underlying problems. This will prevent issues from happening again and again and polish the system periodically as problems occur, so that the stability and integrity of the system only improves over time. Push for real solutions if possible, not band-aids, even if more downtime is needed up front; it is always better to have planned downtime up front than unplanned downtime down the line. Close any monitoring gaps when issues do occur, which is the valid RCA response if not enough information was captured to actually diagnose or resolve the issue.   PTC Tech Support developed a diagnostic data gathering query for Oracle that customers can use, found in our knowledgebase. This is an example of RCA troubleshooting that looks at different database factors, reporting on which queries perform the worst  based on inputted criteria. Another example of troubleshooting is for the Java JVM, where we look at all of the things listed here (below) in an automated, documented process that then generates a report for easy end user consumption.   Don’t hesitate to reach out to PTC Technical Support in advance to go over your RCA processes, to review benchmark discrepancies between what PTC publishes and what your real-life systems show, and to ensure your monitoring is adequate to maintain system stability and availability at all times.  
View full tip
Tune in to The Lean Manufacturer podcast where expert guests bring their outside view of the IIoT and discuss various aspects of manufacturing. Over the course of the series, we’ll cover some of the most important ways the IIoT can maximize manufacturing efficiency and bring value to your organization, including the need for reducing planned and unplanned downtime, enabling operational efficiency, ensuring digital continuous improvement, and so much more.      
View full tip
      Thingworx extensions are a great place to explore UI ideas and get that special feature you want.   Here is a quick primer on Widgets (Note: there is comprehensive documentation here which explores the complete development process ).The intention is not to explain every detail but just the most important points to get you started. I will explore more in additional posts. I also like images rather than lost of words to read. I have attached the simple Hello Word example as a start point and  I'm using Visual Code as my editor of choice.   The attached zip when unzipped will contain a folder called ui and metadata xml file. Within the ui folder there needs to be a folder that has the same name as the widget name. In this case its helloworld.   Metadata file - The 3 callouts are the most import. Package version: is the current version and each time a change is made the value needs to be updated. name: a unique name used through out the widget definition UIResources: The source locations for the widget definition. The UIResources files are used to define the widget in the ide (Composer) and runtime (Mashup). These 2 environments ide and runtime have matching pairs of css (cascading style sheets)  and a js (javascript) files.   The js files are where most of the work is done. There a number of functions used inside the javascript file but just to get things going we will focus on the renderHtml function. This is the function that will generate the HTML to be inserted in the widget location.   renderHtml(helloWorld.ide.js) In this very simple case the renderHtml in the runtime is the same as in the ide renderHtml (helloWorld.runtime.js)   Hopefully you can see that the HTML is pretty easy just some div and span tags with some code to get the Property called Salutation.   So we have the very basics and we are not worried to much about all the other things not mentioned. So to get the simple extension into Thingworx we use the Import -> Extensions menu option. The UI and metadata.xml file needs to be zipped up (as per attachment).  Below is a animated gif that shows how to import and use the widget   Very Quick Steps to import and use in mashup. Video Link : 2147   The next blog will explore functions and allow a user to click the label and display a random message. This will show how to use events   Widget Extensions Click Event
View full tip
Key Functional Highlights Patching & Upgrades Supports upgrading from 8.0.1 using the Manufacturing Apps Installer    Streamlined patch support for customer issues Updated the installer technology to align with ThingWorx platform   App Improvements Fixed bugs with acknowledging alerts Added support for collecting feature data from National Instruments InsightCM product   Controls Advisor Added ability to retrieve KEPServerEX connection information in case the connection is lost or deleted Minor UI improvements   Asset Advisor Updated the UI for anomaly status   Production Advisor Improved the status history widget to align with Asset Advisor Added synchronized zooming to the chart widgets     Compatibility ThingWorx 8.1.0 KEPServerEX 6.2, 6.3 KEPServerEX V6.1 and older as well as different OPC Servers (with Kepware OPC aggregator) Support upgrade from 8.0.1     Documentation ThingWorx Manufacturing Apps Get Started     Download ThingWorx Manufacturing Apps Freemium portal PTC Smart Connected Applications
View full tip
In this blog I will be testing with the WindchillSwaggerConnector, but most of the steps also apply to the generic SwaggerConnector.     Overview   The WindchillSwaggerConnector enables the connection to the Windchill REST endpoints through the Swagger (OpenAPI) specification. It is a specialized implementation of the SwaggerConnector. See Integration Connectors for documentation.   It relies on three components : Integration Runtime : microservice that runs outside of ThingWorx and has to be deployed separately, it uses Web Socket to communicate with the ThingWorx platform (similar to EMS). Integration Subsystem : available by default in 7.4 (not extension needed) Integration Connectors (WindchillSwaggerConnector) : available by default in 7.4 (not extension needed)   Currently, in 7.4, the WindchillSwaggerConnector  does not support SSO with Windchill (it is more targeted for a "gateway type" integration). Note that the PTC Navigate PDM apps are using the WindchillConnector and not the WindchillSwaggerConnector.   Integration Runtime microservice setup   The ThingWorx Integration Runtime is a microservice that runs outside of ThingWorx. It can run on the ThingWorx server or a remote machine. It is available for download from the ThingWorx Marketplace (Windows or Linux). The installation media contains 2 files : 1 JAR and 1 JSON configuration file.   For this demo, I'm installing the Integration Runtime on a remote machine and will not be using SSL.   1. Prerequisite for the Integration Runtime : Oracle Jre 8 (and of course a ThingWorx 7.4 platform server accessible) 2. Create an ApplicationKey in the composer for the Integration Runtime to use for communication to the ThingWorx platform. 3. Configure the Integration Runtime communication - ThingWorx host, port, appKey, ... - this is done on the Integration Runtime server via the JSON configuration file.   My integrationRuntime-settings.json (sslEnable=false, storagePath is ignored) : { "traceRoutes": "true", "storagePath": "/ThingworxStorage", "Thingworx": {     "appKey": "1234abcd-xxxx-yyyy-zzzz-5678efgh",     "host": "twx74neo",     "port": "8080",     "basePath": "/Thingworx",     "sslEnable": "false",     "ignoreSSLErrors": "true"   } } Note : It is important to completely remove the "SSL": {} block when not using SSL   4. Launch the Integration Runtime service (update the JAR and JSON filenames if needed) java -DconfigFile=integrationRuntime-settings.json -jar integration-runtime-7.4.0-b12.jar The Integration Runtime service uses Web Socket to communicate with the ThingWorx platform (similar to EMS). It registers itself with the ThingWorx platform.   Monitoring the Integration Runtime microservice        In the ThingWorx composer : Monitoring > Subsystems > Integration Subsystem      SMAINENTE1D1 is the hostname of my Integration Runtime server.   Custom WindchillSwaggerConnector implementation   Use the New Composer UI (some setting, such as API maps, are not available in the ThingWorx legacy composer) 1. Create a DataShape that is used to map the attributes being retrieved from Windchill WNCObjectDS : oid, type, name (all fields of type STRING)   2. Create a Thing named WNC11Connector that uses WindchillSwaggerConnector as Thing Template 3. Setup the Windchill connection under WNC11Connector > Configuration Authentication Type = fixed (SSO currently not supported) Username = <Windchill valid user> Password = <password for the Windchill user> Base URL : <Windchill app URL> (e.g. http://wncserver/Windchill)   4. Create an API maps under WNC11Connector > Services and API Maps > API Maps (New Composer only) My API Map : New API Map Mapping ID : FindBasicObjectsMap EndPoint : findObjects (choose the first one) Select DataShape : WNCObjectDS (created at step 1) and map the following attributes : name <- objName ($.items.attributes) type <- typeId ($.items) oid <- id ($.items)   After pressing [done] verify that the API ID is '/objects GET' (and not /structure/objects - otherwise recreate the mapping and choose the other findObjects endpoint). 5. Create a "Route" service under WNC11Connector > Services and API Maps > Services (New Composer only) Name : FindBasicObjects Type (Next to [Done] button) : Route Route Info | Endpoint : findObjects (same as step 4) Route Info | Mapping ID : FindBasicObjectsMap-xxxx created at step 4 Testing our custom WindchillSwaggerConnector   Test the WNC11Connector::FindBasicObjects service Note that the id (oid) and typeId (type) are returned by default by the /objects REST API - objName has to be explicitly requested.   Monitoring the Integration Connector        In the ThingWorx composer : Monitoring > Integration Connectors
View full tip
One of topics that are usually of interest when entering the ThingWorx world is integration with third-party systems. Disclaimer: the following guide is intended to be rather comprehensive and guide you in achieving the best integration with your desired system ( !=quick and dirty ). For example, from my experience, customers many times ask: -how can I connect to my hardware device -how can I connect to this device cloud so I can get data from it? -how can I connect to my ERP? With some luck, I hope that at the end of this article I will provide a generic workflow that will help you on achieving the best integration solution for your use-case. We need to write down some requirements (they are not in order; depending on the usecase might not be worth to be answered): 0. What is the usecase (detailed description) ?.      This is by far one of the most important aspects of any software development project.      Please document your usecase with all possible future uses.      For example:           - I want to send information from sensors to the ThingWorx Server, and I want to do TCP Tunnelling to the device and/or Remote Desktop. Or maybe only sending information from sensors and nothing else. Do I need in the future Software Updates or not?           - I want to read the Customer information from my CRM AND also update that information (read/write). 1. Write down system specification for the hardware or software system.           -Available RAM for user apps           -Available Disk Space for User Apps           -Does it have a TCP IP Stack?           -Operating System           -Installed runtimes (Java/.NET - which versions?) 2. Can I access the system or device directly from the ThingWorx Server?      This means answering the question: is my system directly accessible from my server? Or is there a firewall which stops incoming connections?      Another question to answer, is: can I modify my firewall to allow incoming connections? 3. What protocol is my device or system capable of supporting for data transfer?      Example: I have a device which is capable of outputting information through TCP only.                     I have a device who can only do HTTP callbacks to a HTTP server.                     I have Microsoft SQL, to which I can connect through ADO.NET or JDBC.                     I have a third party service billing provider who supports interfacing via HTTP Webservices (SOAP or REST).                     I have a device supporting CoAP.      Typically all third party software systems support communication via Webservices. 4. Can I configure and/or deploy new software to my device or system?      We need to have this question answered, because on some cases it might make more sense to write some logic on the system or device.      For example if I want to access data from an SQL server and my usecase might require some processing for which that SQL server is better suited to do, it might be much more efficient to have that logic stored as a Stored Procedure there and I just call it from ThingWorx.       Or in the case of Windchill, it might make more sense to write an InfoEngine task to do my functionality than writing that on the ThingWorx side.      Possible example answers:                     -My device is already deployed in the field and I can not modify the configuration at all.                     -My device is a new product, so I can put whatever software I want on it.                     -I only have read access to my software system, so I must do all processing externally. If you wrote down all of those it is time to determine what are the integration options for us. The typical workflow that I follow is the next one: I look for any Out-Of-The-Box supported protocol (determined at step 3) and then implement the needed functionality in the language that is best suited for my usecase (Javascript usually). The list of protocols that the platform supports is listed in different places: -PTC Help Center Link -ThingWorx Marketplace - https://marketplace.thingworx.com/items The key point is that the list is alive and updated by both our partners and us. Usually the preferred way to write logic is by using the Javascript services. It makes it incredibly fast to write down your business logic without having the need to recompile. The elements from the ThingWorx ecosystems that we can use are the following: -the ThingWorx server itself (it has built in support for calling external Webservices) -ThingWorx Extensions. They are Java written pieces of code that can help you achieve your usecase. To be used whenever your ThingWorx server OOTB functionality (or Marketplace Extensions) does not allow you to develop your usecase. There is no actual need to write an Extension if somebody else already developed that for you and published in the ThingWorx Marketplace https://marketplace.thingworx.com/items      A link for understanding Extension is the following: How to rapidly develop ThingWorx IIoT Extensions -ThingWorx Integration Connectors -ThingWorx Edge Micro Server: https://developer.thingworx.com/ems -ThingWorx Edge SDKs: https://developer.thingworx.com/sdks Examples: -I have an third party Server which allows me to send SMS and Voice messages through it via its Rest API.      Answer: best here is to use the OOTB Webservices support from ThingWorx, which exposes the HTTP verbs, like GET, POST, PUT, via the ContentLoaderFunctions -I have a device which has a TCP stack that is capable only to do HTTP calls.      Answer: I can point that device to do calls against the REST API of ThingWorx, in order to update data directly there. -I have a fleet of 300.000 devices which are sending their data to an MQTT server.      Answer: In this case I can use the MQTT Extension that is offered by ThingWorx -I have an external SQL server that does not accept inbound connections (behind a firewall) but I must get data from it. Network will however allow outbound connections      Answer: use the ADO.NET Edge Client that must be installed in a location accessible to that server. The ADO.NET Edge Client will connect to the Server and then to the ThingWorx platform allowing use of SQL statements directly from within the platform. -I have a device who only accepts TCP connections and I want to read data from it. It sends data only after receiving a command through TCP.      Answer: Use the TCP Extension available in the ThingWorx Marketplace. It is built specifically for this usecase -I have a device which has lots of RAM and Disk Space and I must send data from it, while allowing software updates in the future.      Answer: depending on your preferred coding language you can use either the ThingWorx Edge Microserver (for which you must write code in LUA) or write an implementation in one of the ThingWorx Edge SDKs. A key point here is to understand that the coding effort is identical in theory, and is only limited by the experience you have and the functionality that may be available easier in Java, vs LUA, vs C, vs. Net. I appreciate feedback to this article in the hope of being able to continuously improve it.
View full tip
This post will cover the challenges I've had while going through the setup of .NET SDK based ADO Service for SQL Server DB Connection. I'll be starting from the scratch on setting up the service for this to present full picture on the setup. Pre-requisite 1. Download and install Microsoft SQL Server Express or Enterprise edition, for testing I worked with Express edition : https://www.microsoft.com/en-us/sql-server/sql-server-editions-express 2. Once installed, it's imperative that the TCP/IP Protocol is enabled in the SQL Server Configuration Manager for the SQL Server 3. Download ThingWorx Edge ADO Service from PTC Software download page What is ThingWorx ADO Service? An ActiveX Data Object service allowing connection to a Microsoft database source e.g. MS SQL Server, MS Excel or MS .NET application to the ThingWorx platform. It is based on the ThingWorx .NET SDK. Installing ADO Service Let me begin by saying this is just a summary, in a crude way of course, of ThingWorx Edge ADO Service Configuration Guide. So when in doubt it's strongly recommended to go through the guide,also provided together with the downloaded package. I'll be using the ThingWorx ADO Service v5.6.1, most recent release, for the purpose of this blog. Depending if you are on x86 or x64 Windows navigate to the C:\Windows\Microsoft.NET for accessing the InstallUtil.exe You'll find the above specified file under following two locations, use the one that applies to your use case. i) For x64 : C:\Windows\Microsoft.NET\Framework64\v4.0.30319 ii) For x86 : C:\Windows\Microsoft.NET\Framework\v4.0.30319 1. Copy over the desired InstallUtil.exe to the location where you have unzipped the ADO Service package, the one downloaded above. e.g. I've put mine at C:\Software\ThingWorxSoftware\ADOService\ 2. Start a command prompt (Windows Start Menu > Command Prompt) and execute the InstallUtil.exe ThingWorxADOService.exe 3. This should create a service and some additional info in the \\ADOService folder in the form of InstallUtil.InstallLog 4. Check the log for confirmation, you should see something similar Running a transacted installation. ...     .... The Commit phase completed successfully. The transacted install has completed. ​​5. In Windows Explorer navigate to the folder containing all the unzipped files, and edit the AdoThing.config 6. For this blog I've security disabled, though obviously in production you'd definitely want to enable it 7. Configure the ConnectionSettings as per your requirement (refer to the guide for more detail on settings), below I'm noting the settings that will require configuration in its most minimum form (I've also attached my complete AdoThing.config file for reference) "rows": [       {         "Address": "localhost",         "Port": 8080,         "Resource": "/Thingworx/WS",         "IsSecure": false,         "ThingName": "AdoThing",         "AppKey": "f7e230ac-3ce9-4d91-8560-ad035b09fc70",         "AllowSelfSignedCertificates": false,         "DisableCertValidation": true,           "DisableEncryption": true       }     ] 8. Configure the connection string for the SQL Server in following section, in the same file opened above     "rows": [       {         "ConnectionType": "OleDb",         "ConnectionString": "Provider=SQLNCLI11;Server=localhosts\\SQLEXPRESS;Database=TWXDB;Uid=sa;Pwd=login123;",         "AlwaysConnected": true,         "QueryEnabled": true,         "CommandEnabled": true,         "CommandTimeout": 60       }     ] 9. Just to highlight what's what in ConnectionString above: "ConnectionString": "Provider=SQLNCLI11;Server=<Machine/ClientName>\\SQLServerInstanceName;Database=<databaseName>;Uid=<userName>;Pwd=<password>;" 10. To get correct connection string syntax for different source refer to the ConnectionStrings.com 11. Save the file 12. Navigate to the windows services by opening Windows Start > Run > services.msc 13. Check for the service ThingWorx .NET ADO Client as you'll have to start it if it's set to Manual, like so in my case Following message will be logged on successful connection  in the DotNETSDK -X-X-X.log : [Critical] twWs_Connect: Websocket connected! At the end of the blog I'll share some of the errors that I came across while working on this and how to go about addressing them. Creating and connecting to Remote Database Thing Now, let's navigate to the ThingWorx Composer and create a Thing with RemoteDatabase Template to consume the resource created above in the form of ADO Service. I've named my thing as AdoThing while creating it in ThingWorx Composer, which matches with the ThingName used in the AdoThing.json file. If everything went through as needed you should see the isConnected = true in the AdoThing's Properties section. Since, this is a Database thing I can now go about creating all the required services concerning the Create, Update, Delete (CRUD) operations, just like for any database for created using the RDBMS Connector. Handling errors while setting up the ADO Service Here are some of the errors that I encountered while setting up the ADO service for this blog: Error 1: com.thingworx.ado.AdoThing Cannot connect to database. : System.Data.OleDb.OleDbException: Login timeout expired Note: Logged in DotNetSDK-X-X-X.log Cause & Resolution: - Service is not able to successfully reach or authenticate against the SQL Server Express DB instance - Ensure that the TCP/IP is enabled for the Protocols for the SQL Express, as I have shared in the screenshot above - Make sure that the username / password used for authenticating with the database is correctly provided while configuring the settings for the OLEDB section in    AdoThing.config Error 2: com.thingworx.ado.AdoThing GetTables OleDbException error : System.Data.OleDb.OleDbException Note: Logged in Application.log from ThingWorx platform Cause & Resolution - This exception is thrown when user attempts to check for the available tables, while creating the service in the ThingWorx Composer - Resolution to this is similar to that mentioned above for Error 1 Error 3: [U: SYSTEM] [O: com.thingworx.ado.AdoThing] OleDbException [code = -2147217865, message = Invalid object name 'TWXDB.DemoTable'.] executing SQL query Note: Logged in Application.log from ThingWorx platform while testing/executing the SQL service created in the ThingWorx Composer Cause & Resolution - The error is due to the usage of DB name in front of the table name, it's not required since the DB name is already selected in the connection String Error 4: [O: com.thingworx.Configuration] Could not read configuration file. : Newtonsoft.Json.JsonReaderException: Bad JSON escape sequence: \S. Path 'Settings.rows[0].ConnectionString', line 656, position 71. Note: Logged in DotNetSDK-X-X-X.log Cause & Resolution - This is caused due to the "ConnectionString": "Provider=SQLNCLI11;Server=<machineNameOrIP>\SQLEXPRESS;Database=TWXDB;Uid=sa;Pwd=login123;", - Json requires this to be escaped thus switching to "ConnectionString": "Provider=SQLNCLI11;Server=<machineNameOrIP>\\SQLEXPRESS;Database=TWXDB;Uid=sa;Pwd=login123;", resolved the issue - Among many other, https://jsonformatter.curiousconcept.com/​ is quite helpful in weeding out the issues from the JSON syntax Error 4: [O: com.thingworx.ado.AdoClient] Error while initializing new AdoThing, or opening connection to Platform. : System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.     at com.thingworx.communications.client.TwApiWrapper.twApi_Connect(UInt32 timeout, Int32 retries)     at com.thingworx.communications.client.TwApiWrapper.Connect(UInt32 timeout, Int16 retries)     at com.thingworx.communications.client.BaseClient.start()     at com.thingworx.ado.AdoClient.run() Note: Logged in DotNetSDK-X-X-X.log Cause & Resolution - This error is observed when using FIPS version of the  ADO Service, esp. when downloaded from the ThingWorx Marketplace - Make sure to recheck the SSL configuration - When not using SSL check that the x64 and x86 directories only contain twApi.dll as by default FIPS version contain two additional dlls i.e. libeay32.dll & ssleay32.dll in both x64 & x86 directories
View full tip
Hello everyone, This post is meant to fill the gap that Basic Rules of ThingWorx Development is having. You can follow these rules even before starting the development process and keep them in mind to have an organized and easy to maintain application. I will update this post in the future with more best practices and advice. Best Practices and suggestions: In order to have a clean and quick progress in any project the approach should be modular. If the modular approach is implemented also the development process should be thought of in a modular way. This will give much needed independence to each individual developer especially if the team concurrently works on the same instance. Some rules need to be in place in order for the project to be as smooth as possible: Every developer must have its own user. This is more important when developing on the same Thingworx instance but it’s a good practice when developing on individual instances as well. Every developer will be responsible for complete modules, from the respective screens of the GUI to the functionality services and business logic. If concurrent work on the same Entity needs to happen then communication between the developers and time sharing on that entity is needed without developers overwriting each other’s code. Don't decide to go into edit mode if there is someone else already editing. That will get you to a dead end. For the point no. 3 to work, after editing an Entity each user must press the Cancel Edit button and leave that Entity in View mode. When searching for services or properties developers should avoid pressing on the name of the Entity which is a link that directly opens the Entity in Edit mode they should rather use the button with the magnifying glass to the left of the name that will then take them in View mode. As a result of the modular approach each module will have its own Utility Thing that will contain services, properties, events and subscriptions that help develop the functionality for that module. Each module will have its own tags and the format could be: <Client_Name><GUI/Business><Module_Name>   8. The integration of the modules will be done in the Master by a single person in charge with that master or by each developer at a time.   9. Depending on the case the Data Model could be treated as a module in its own right or can be integrated in each module if the project permits. How to manage multiple users working on the same code in Composer: (Thanks to Pai Chung) Currently Thingworx within the development environment allows you to heavily document all your works, that includes ‘Save with Comment’. We encourage the use of the Documentation field and the ‘Save with Comment’ option. However generally development is not isolated to one environment. Thingworx provides several ways to back up the information. Backup – this is a true Database backup that creates an additional database in ThingworxBackupStorage and basically can be used as a restore, by copying it back into ThingworxStorage Export to ThingworxStorage – this is a full model export (with or without data) that can be triggered at any time. It can use Date filters to export according to Modified date. This is server side. Export to File – this allows you to export a single or group of entities/data according to a variety of filters. This is client side. Export to Source Controlled Entities – this allows you to export to a file folder structure or Zip that can be easily checked into a Source Control system. How to approach Source Control: After some initial modeling, Export to Source Control Entities and check this into your Source Control system From this point forward all developers have to follow a Check in/check out process Every time an Entity Group security setting is made, Export to ThingworxStorage and also check that into Source Control overwrite the previous. All in use Extensions should be in one zip and also reside in Source Control To do a restore or deploy Install the Platform Install extensions Import from ThingworxStorage the last Export checked in Import each single Entity file, in the proper order. Import each single Data file   6.  Clean up dead entities (if there is a reference list) Additional steps to take to help safeguard the development. Make sure the Automatic backup is running Export the Entity to a subfolder with the Date of the Edit     3.  Full Export to ThingworxStorage to run every day after development stars - This can be scripted and triggered by a timer or scheduler subscription (<Server>/Thingworx/ExportDatabase/?WithData=true). In this way you have a backup with everything that was on before you started working each day so you can roll back if an error occurs. CONTINUED 7 Sep 2015 How to organize wiring needs when developing the GUI: Starting from the idea that we can divide the GUI elements in Display Elements and Action Elements I have created a common form in order to be filled with information necessary for the wiring of that Element. UI Element Type Display Element / User Action Element Thing Name Name of the thing where data / service is found Service Name Service inside the Thing that returns the data / is the subject of the action Property(ies) Name Thing property / column name (when service returns an infotable) for Data Elements / Input parameters for the service to be run if User Action Element Additional Logic Additional information regarding the way the information sources change when preconditions are met. Usually means new services or mashup logic is needed.  I suggest that an additional companion document to the GUI description document to be created. This document will contain the previous form (table) for each screen/slide so that the work on specific screen/slide could be done independently. To be continued...
View full tip
Video Author:                     Christophe Morfin Original Post Date:            September 13, 2016 Applicable Releases:        ThingWorx Analytics 52.2 to 8.0   Description: In this video we cover the installation of the UploadThing Module.   Useful Links: How to copy files from Windows to Linux  
View full tip
Announcements