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

Community Tip - Did you know you can set a signature that will be added to all your posts? Set it here! X

IoT Tips

Sort by:
I imagine a lot of people that face this problem might be using Session Parameters, but there is a secret lost Ninja art that allows you to do it with Mashup parameters which is much more contextual and direct. The key is to have Mashup parameters with the same name. End Result Starting out I am on my main mashup, you can see the Tree Data in the Grid below Clicking on the next node now shows the new mashup and the TO field inside. That To value was passed in using a mashup parameter Clicking the next node, you can see it is actually a different mashup, but I am still passing the TO value How is it done: Here is my mashup with the Tree and Contained mashup, you can see the bindings are in place already, but how did I do it, since the Contained Mashup is empty? First create the new mashups with a mashup parameter named the SAME in this case EntityName Here is Mashup2 and you can see the Mashup parameter with the same name EntityName bound to one of the Value Displays Now how do I bind from my main mashup? What you need to do is to temporarily assign one of the Mashups to the Contained Mashup, here I am showing Mashup1 assigned. This will now allow you to bind not just the Mashup Name, but also bind a value to the Mashup Parameter in that Mashup. Just drag your selected row values onto the contained mashup. Here you can see the parameter showing as a property, I just dropped my value on the contained mashup and I can bind to Name (name of the mashup to show) and EntityName (the value I want to pass to the mashup parameter) Now just remove the assigned mashup from the Contained mashup and you’ll note that the bindings stay intact. That’s it!
View full tip
In this post, I show how you can downsample time-series data on server side using the LTTB algorithm. The export comes with a service to setup sample data and a mashup which shows the data with weak to strong downsampling.   Motivation: Users displaying time series data on mashups and dashboards (usually by a service using a QueryPropertyHistory-flavor in the background) might request large amounts of data by selecting large date ranges to be visualized, or data being recorded in high resolution. The newer chart widgets in Thingworx can work much better with a higher number of data points to display. Some also provide their own downsampling so only the „necessary“ points are drawn (e.g. no need to paint beyond the screen‘s resolution). See discussion here. However, as this is done in the widgets, this means the data reduction happens on client site, so data is sent over the network only to be discarded. It would be beneficial to reduce the number of points delivered to the client beforehand. This would also improve the behavior of older widgets which don’t have support for downsampling. Many methods for downsampling are available. One option is partitioning the data and averaging out each partition, as described here. A disadvantage is that this creates and displays points which are not in the original data. This approach here uses Largest-Triangle-Three-Buckets (LTTB) for two reasons: resulting data points exist in the original data set and the algorithm preserves the shape of the original curve very well, i.e. outliers are displayed and not averaged out. It also seems computationally not too hard on the server. Setting it up: Import Entities from LTTB_Entities.xml Navigate to thing LTTB.TestThing in project LTTB, run service downsampleSetup to setup some sample data Open mashup LTTB.Sampling_MU: Initially, there are 8000 rows sent back. The chart widget decides how many of them are displayed. You can see the rowcount in the debug info. Using the button bar, you determine to how many points the result will be downsampled and sent to the client. Notice how the curve get rougher, but the shape is preserved. How it works: The potentially large result of QueryPropertyHistory is downsampled by running it through LTTB. The resulting Infotable is sent to the widget (see service LTTB.TestThing.getData). LTTB implementation itself is in service downsampleTimeseries     Debug mode allows you to see how much data is sent over the network, and how much the number decreases proportionally with the downsampling.   LTTB.TestThing.getData;   The export and the widget is done with TWX  9 but it's only the widget that really needs TWX 9. I guess the code would need some more error-checking for robustness, but it's a good starting point.  
View full tip
Hi everyone,   Maybe you got my email, I just wanted to post this also here.   I built a CSS generator for a few widgets, 8 at the moment. This is on a cloud instance accessible by anyone.   Advantages:      - don't have to style buttons and apply style definitions over and over again      - greater flexibility in styling the widget      - you don't have to write any CSS code   The way this works: you use the configurator to style the widget as you want. Use also a class to define what that widget is, or how it's styled. For example "primary-btn", "secondary-btn", etc. Copy the generated CSS code into the CustomCSS tab in ThingWorx and on the widget, put the CustomClass specified in the configurator.   As a best practice, I'd recommend placing all your CSS code into the Master mashup. And then all your mashups that use that master will also get the CustomCSS. So the only thing you have to do to your widgets in the mashups, is fill the CustomClass property with the desired generated style. Also, comment your differently styled widgets by separating them with /* My red button */ for example.   The mashups for this won't be released, this will only be offered as a service. As you'll see in the configurator, they are not that pretty, the main goal was functionality.   Here is the link to the configurator: https://pp-18121912279c.portal.ptc.io/Thingworx/Runtime/index.html#master=CSSMaster&mashup=ButtonVariables User: guest Password: guest123123   Give it a go and have fun! 🙂   NOTE: I will add more widgets to this in the future and will not take any requests in making it for a specific widget, I make these based on usage and styling capabilities.    
View full tip
User Localization vs. Browser Localization Localization in ThingWorx is mainly based on Localization Tables and tokens which are used as a placeholder for the actual word / phrase in a particular language. There's a blog at https://community.thingworx.com/community/developers/blog/2016/08/15/managing-and-using-localization-in-thingworx which is explaining in-application localization in detail. Language preferences are however only considered by the user's settings. For the organization login pages at http://<server>/Thingworx/FormLogin/<organizationName> there's no defined user yet. As the user has not logged in yet, ThingWorx will have no user preferences to identify the need for a specific language. Instead the browser language is used. The login / password-reset page is constructed at runtime via .jsp templates. Via JavaScript the browser language is detected and language specific configuration files are considered. When such a configuration file is present, its tokens will be used to replace the data-i18n placeholders in the .jsp files. Customizing the login related localizations The localization files are stored in <Tomcat>\webapps\Thingworx\Common\locales\ For each language there's a subfolder - by default this is "en" for English. The language and therefore folder to be used will be determined by the user's browser settings. Whatever is top in the language list will be considered first. If a folder, e.g. for German (de), French (fr) or Spanish (es) exists, ThingWorx will use this for localization. In the folder, there's the translation-login.json file. It holds all the tokens required for the login relevant translations / localizations. The FormLogin.jsp holds e.g. the token [placeholder]tw.login.labels.name This is a placeholder (which means text to be overwritten in a textfield in case the textfield is empty). The actual localization can be found in the translation-login.json going down the json object structure to "tw" > "login" > "labels" > "name" which results as Name in the English translation. tw.login.labels.password-title would result in the following String: Password must be at least 5 characters Creating custom languages To create a custom language besides English, copy the en folder and rename it to the correct language short name, from Afar (aa) to Zulu (zu). A list of Language Code References can be found at https://www.w3schools.com/tags/ref_language_codes.asp After copying the folder, open the translation-login.json and alter the resulting Strings into the correct language variant. As soon as the correct translation-login.json is created, it will be considered for localization. No need to restart Tomcat.
View full tip
Create a new Thing using the Scheduler Thing Template. The Scheduler Thing will fire a ScheduledEvent Event when the configured schedule is fired. The event is automatically present and does not need to be added manually. Configuration   The Scheduler Configuration is quite straightforward and allows for an exact setup of schedule based on units of time, e.g. seconds, minutes, hours, days of week etc. It can be accessed via the Thing's Entity Configuration   Configuration allows for Changing the runAsUser context - in which the Events will be handled. The user will need visibility and permission on e.g. executing Services or depending Things, which are required to run the Service triggered by the Event. Changing the Schedule - in which time the Events will be fired (by default every minute). The schedule is displayed in CRON String notation and can be changed and viewed in detail by clicking on "More". The CRON String will be generated automatically based on the inputs. Schedules can be configured in Manual mode - allowing for full configuration of each and every time based attribute. Schedules can be configured for a specific time Type - allowing for configuration only based on seconds, minutes, hours, days, weeks, months or years. Below screenshots show schedules running every minute and every Saturday / Sunday at 12:00 ("Every Weekend Day").     Services   Scheduler Things inherit two Services by default from the Thing Template DisableScheduler EnableScheduler These will activate / de-activate the Scheduler and allow / disallow firing Events once a scheduled time is reached If a Scheduler is currenty enabled or disabled can be seen in its properites  
View full tip
Style theming is a Beta feature that allows you to customize the look of your mashups and widgets.   A style theme is a set of styling properties for elements such as text, colors, and lines that you can apply to a mashup. You can manage styles for multiple mashups more easily by using style themes. Style theme apply on a mashup level, unlike style definitions, which apply on a widget level. When you apply a style theme to a mashup, all embedded widgets and mashups will derive styling properties from the style theme for the top level mashup. You can perform the following tasks:   • Create and modify style themes. • Apply a style theme to one or more mashups. • Reuse a style theme by using Import/Export. • Define custom CSS for a style theme. CSS rules are applied to all mashups that use the style theme.   Style theme support is limited to the following types widgets: • New widgets — You can only apply a style theme to these widgets. • Hybrid widgets — You can use style definitions or a style theme to style these widgets.   NOTE: You can enable or disable style themes for hybrid widgets by using the (BETA) UseThemeForHybrids property in the mashup properties panel. However, you cannot use style definitions with web component widgets.   To read more about Base Theme, Creating, and Modifying Style Themes, refer to our ThingWorx Help Center.
View full tip
Initial Objective statements This post is about getting D3 connected as an extension to Thingworx. There are a number of existing extensions using D3 but I wanted to explore a simple use case to make it easier to get into and bring out 2 additional points Using an infotable as data input Resize The output looks like the image below and the data was generated by a Timer based random value generator that set the values on a Thing every minute. The data into the Widget is from a core service QueryHistory (a wrapped service that uses QueryProperyHistory) In this example I will use temp as the variable in focus If you have never created an extension take a look at Widget Extensions Introduction which provides a start to understanding the steps defined below, which are the core points to keep it relatively short. The extension will be called d3timeseries and will use the standard design pattern Create a folder called d3timeseries and create a subfolder ui and a add a metadata.xml file to the d3timeseries From there create the files and folder structure define the metadata.xml using CDN url for D3 url url="https://d3js.org/d3.v4.js" legend url = "https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.25.3/d3-legend.js" Also check out https://d3js.org/ which provides documentation and examples for D3 For the initial set of Properties that control the D3 will use DataAsINFOTABLE (Data coming into d3) Title XLegendTitle YLegendTitle TopMargin BottomMargin LeftMargin RightMargin Note: we are not using Width and Height as in previous articles but setting 'supportsAutoResize': true, Below shows the general structure will use for the d3timeseries.ide.js properties After deploying the extension  (take look at Widget Extensions Introduction to understand the how) we can see its now possible to provide Data input and some layout controls as parameters From there we can work in the d3timeseries.runtime.js file to define how to consume and pass data to D3. There a 4 basic function that need to be defined this.renderHtml this.afterRender this.updateProperty this.resize renderHtml afterRender updateProperty resize The actual D3 worker is drawChart which I will break down the highlights I use an init function to setup where the SVG element will be placed The init is called inside drawChart Next inside drawChart the rowData incoming parameter is checked for any content we can consume the expected rows object Next the x and y ranges need to be defined and notice that I have hardcoded for d.timestamp and d.temp these 2 are returned in the infotable rows The last variable inputs are the layout properties Now we have the general inputs defined the last piece is to use D3 to draw the visualization (and note we have chosen a simple visualization timeseries chart) Define a svg variable and use D3 to select the div element defined in the init function. Also remove any existing elements this helps in the resize call. Get the current width and height as before Now do some D3 magic (You will have to read in more detail the D3 documentation to get the complete understanding) Below sets up the x and y axis and labels Next define x and y scale so the visualization fits in the area available and actually add the axis's and ticks, plus the definition for the actual line const line = d3.line() Now we are ready for the row data which gets defined as data and passed to the xScale and yScale using in the const line = d3.line() After zipping up and deploying and using in a mashup you should get a D3 timeseries chart. Code for the QueryHistory logger.debug("Calling "+ me.name + ":QueryHistory"); // result: INFOTABLE var result = me.QueryPropertyHistory({ maxItems: undefined /* NUMBER */, startDate: undefined /* DATETIME */, endDate: undefined /* DATETIME */, oldestFirst: undefined /* BOOLEAN */, query: undefined /* QUERY */ }); Thing properties example Random generator code me.hum = Math.random() * 100; me.temp = Math.random() * 100; message = message + "Hum=" + me.hum+ " "; message = message + "Temp=" +me.temp+ " "; logger.debug(me.name + "  RandomGenerator values= " + message ); result = message; Previous Posts Title Widget Extensions Using AAGRID a JS library in Developer Community Widget Extensions Google Bounce in Developer Community Widget Extensions Date Picker in Developer Community Widget Extensions Click Event in Developer Community Widget Extensions Introduction in Developer Community
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
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
We will host a live Expert Session: "Thingworx Mashup 101 - Do's and Don'ts" on February 24th, 13h30 EST.   Please find below the description of the expert session and the registration link.   Expert Session: Thingworx Mashup 101 - Do's and Don'ts Date and Time: February 24th, 13h30 EST Duration: 1 hour Host: Aanjan Ravi - Technical Product Manager Registration Here: https://www.ptc.com/en/events/thingworx-mashup-101   Description: This session covers the most common and useful tips about how to correctly use Mashup builder, Widgets and Layouts – and what to avoid -  to create applications with good principles of UI/UX and easier to maintain.   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
In the ptc-windchill-extension-1.0.0-14.zip archive there is an extension called infotableselector_ExtensionPackage.zip​ . This extension enables the use of the Widget called Infotable Selector, which can be used to clear the selection in a grid. For how to use this widget, take a look at the picture:
View full tip
  Maintain cookies and security information by implementing session parameters in your application.   Guide Concept   This project will introduce creating and accessing session data from a User logged into your application. Session data is global session-specific parameters that can be used on the Client and Server side.   Following the steps in this guide, you will be able to access the logged in User's information and their set values.   We will teach you how to access session data, that can later be used to provide Users with unique experiences and a more robust application.   You'll learn how to   Create Session Data Access Stored Session Data   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes     Step 1: Completed Example   Download the completed files for this tutorial:  Sessions.xml.   The Sessions.xml file contains a completed example of session parameters. Utilize this file to see a finished example and return to it as a reference if you become stuck during this guide. 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.     In the bottom-left of Composer, click Import/Export.     Click IMPORT.     In the Import pop-up, keep the default values and click Browse. Navigate to the Sessions.xml file you downloaded. Select it and click Open. Click Import in the Import pop-up. Click Close to close the pop-up.       Step 2: Create Session Parameters  Click the Browse folder on the left-hand side. Under System, select Subsystems.     Filter for UserManagementSubsystem and open it in Edit mode.     Select Services. Filter for the AddSessionShape Service.     Click the Play button to open the Execute window. Enter UserLogin (the provided ThingShape) as the name input field. Click Execute.     Click Done.   You've just created your first Session Parameter. These values are used for content held in a cookie for a website or information that might be static for the User or session.   Best Practice: For information that will be static for the entire application and not based on the session, use a database option or a stored value in a Thing.       Step 3: Access Session Parameters   Click the Browse folder on the left-hand side. Under System, select Resources.   Filter for CurrentSessionInfo and open it.   Select Services. Filter for the GetGlobalSessionValues Service.   Click the Play button to open the Execute window. Click Execute. You will notice the result is a list of the properties in the UserLogin ThingShape. Your result might differ from mine.   Click Done.   NOTE: There is a difference between Session parameters and Mashup parameters. Mashups can have input values that will be used for services or content of that Mashup ONLY. Session parameters are based on the user using the application in a session. This data will be accessible throughout the application and last until they have completed their usage. This guide shows how to create Session parameters that are considered global session parameters.     Step 4: Next Steps   Congratulations! You've successfully completed the Create Session Parameters guide, and learned how to: Access a logged-in user's information and their set values Use session data to provide users with unique experiences and a more robust application   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Create Custom Business Logic Build Data Model Introduction   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource  Link Community Developer Community Forum Support Session Parameter Help Center  
View full tip
Events   Timers and Schedulers both come with a specific Event inherited from the Thing Template: Timer ScheduledEvent Both have a Data Shape allowing to capture the timestamp of when the Event was actually fired. Events in ThingWorx are triggered when a specific condition is met. In this context the condition is met and the Event is fired when a Timer has expired or a Scheduler's time is reached. Once an Event is triggered, Subscriptions will take care of executing custom Services to react to the Event. Subscriptions   Subscriptions listen to Events and can be used to react to certain Events with running custom Service scripts. To follow-up on Timers and Schedulers, a new Subscription must be created, listening to any related Event fired. Add a new Subscription to the Thing with       As the Subscription is usually listening to the Thing that it is configured on, the Source has to be left empty. When listening to other Entities' Subscriptions the corresponding Entity can be picked in the Source Entity picker. Ensure to check the Enabled checkbox to actually enable the Subscription and allow it for executing code in the Script area. The following Script will log into the ScriptLog once the Timer Event is fired     The following Script will log into the ScriptLog once the ScheduledEvent Event is fired  
View full tip
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
      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
1. Create a network and added all Entities that implement from a specific ThingShape in the network 2. Create a ThingShape mashup as below Note: Bind the Entity parameter to DynamicThingShapes_TracotrShape's service GetProperties input EntityName. Laso bind mashup RefreshRequested event to that service 3. Create a mashup named ContentShape, add Tree widget and ContainedMashp in it 4. Bind Service GetNetworkConnection's Selected Row(s) result and Selected RowsChanged event to ContainedMashup widget Note: Master can total replace ThingShape mashup. Suggest to use Master after ThingWorx 6.0
View full tip
We will host a live Expert Session: "Thingworx Mashup 101 - Do's and Don'ts" on February 24th, 13h30 EST.   Please find below the description of the expert session and the registration link.   Expert Session: Thingworx Mashup 101 - Do's and Don'ts Date and Time: February 24th, 13h30 EST Duration: 1 hour Host: Aanjan Ravi - Technical Product Manager Registration Here: https://www.ptc.com/en/events/thingworx-mashup-101   Description: This session covers the most common and useful tips about how to correctly use Mashup builder, Widgets and Layouts – and what to avoid -  to create applications with good principles of UI/UX and easier to maintain.   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 might be a well-known topic for some, but I recently had a need that Event Routers fit into perfectly and wanted to share. If you have some neat applications for Event Routers on mashups, feel free to reply!   What? Event Routers are a function on Mashups that let you connect multiple inputs to a single output. For my use case, this was extremely helpful to let me have two different Service Outputs go to the same Widget. They are a really simple tool that can save a lot of headache.   How? Event Routers work by funneling the latest data through to a single output. This is particularly useful for  user-activated actions with the output tied to a widget or another service. The Event Router automatically activates when any one of the Inputs changes.   Example I have two services that generate HTML from different sources, but I want to display just the latest one that the user had activated in a single HTML Text Area widget. The two different services are activated with two different buttons. But how do I show these two outputs in a single widget? Create an Event Router with two HTML inputs!         Now I just tie each service output to the Inputs and tie the Output to the HTML Text Area Text (note: the icon for Input2 is incorrect—it should be HTML as well; this system is running 8.5.1, perhaps it's an issue in that release).         Now when the user clicks on either button, the correct service’s HTML is sent to the HTML Text Area. Ta-da!   P.S. I noticed in some older posts that Event Routers used to be a widget or extension that came and went. Now (8.5+) it is baked into the Functions on the far right side of Mashup Builder.
View full tip
Warning This post is quite long, has various chapters and you might get bored reading it. If you just want a summary read the "Use case" and "Conclusion" chapter - and maybe the "Required Logic" chapter, because I made a cool graph for it. The rest is all about implementation... Introduction I recently had the opportunity to deliver a ThingWorx training for Saint Gobain. One of the use cases for their ThingWorx application is monitoring machine errors and outages on the production line. If an outage or error status is triggered, the machine operator will see a popup on the monitoring screen where he is forced to select a root cause. This root cause will then be persisted in ThingWorx for more data transformation, analytics and reporting - like cost analysis or optimization opportunities. During the training we were also discussing on how such a forced root cause monitoring can be implemented via Mashups and the usage of modal popups. I've compiled the details into this post as it might also interest other developers. The ThingWorx Entities I'm using in this example can be downloaded from here Note: I'm using the word "Alert" here - but not in the context of a ThingWorx Property Alert... just beware to not be confused due to the wording. Use Case One of the requirements for Saint Gobain's IoT Solution was an interactive alert monitoring directly in the factory on the production machines. Let's say the machine has stopped, the root cause should be recorded. For this an interactive popup will be displayed on the machine's monitoring display and an employee has to choose the root cause from a pre-defined list. This could be planned outages, e.g. for maintenance or unplanned outages, e.g. material jam. The root cause will then be recorded and a history of outage causes can be stored in a ThingWorx value stream. This can then be later analyzed with e.g. ThingWorx Analytics capabilities to understand and optimize the machine's production capabilities and efficiency. As the root cause must be entered, the popup will be forced to be displayed when a certain condition / criteria is met - and it will only disappar when a root cause is chosen. The user should not be able to interact with any other elements of the Mashup and not be able to just close the popup. The popup will close itself and reset the initial condition once the root cause has been identified and chosen. Requirements Required Entities Required Logic Note: Just to make it easier to manage and export Entities, I will add all of the created elements in a new Project called RootCausePopups. All of the elements will have a "rcp_" added in front of their name - just to make it easier for me to find and identify them. Implementation Before we start - set a Project Context Create Entities Create a Popup Mashup Create the Main Mashup Testing the Mashups Conclusion Certain conditions (like the state of a checkbox) can be used to trigger modal popups. A modal popup forces a user interaction and the interaction will not offer any other option until a choice is made. With these parameters it's easy to have mandatory reaction from users when it's important to capture data which rely on the analysis of an engineer or a user - e.g. reasons for machine outages. Using this technique there's not much training required for staff, other than pushing a button with an option of their choice - this saves quite some time in capturing data in any other way (e.g. updating Excel files or manual pen-and-paper techniques). As this data is now part of the ThingWorx instance it can be used for further transformation, analysis or just for monitoring purposes There's of course more possibilities when it comes to states and formatting which would exhaust the context of this post - but feel free to explore... In the example we wouldn't need the textbox, but it's there to demonstrate if the correct values are persisted or not In the example we could of course also set the visibility of the checkbox to false, so that we would only see the popup and the Grid holding historic information We could also create different StateDefinitions to color-format / text-format the input differently from the output in the Grid If you found this interesting (and actually made it to the end of this post) - feel free to play with this concept a bit more... The dependencies might seem a bit difficult, but it should be easy to implement and to adjust to your own ideas and requirements.
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
Note: The following tutorial are based on a Thingworx/CWC 9.5. Steps and names may differ in another version. Context As a human reaction, the tracked time displayed may be misperceived by the Operator. It can lead to a reject of the solution. CWC doesn’t have (yet?) the capability to configure the visibility to hide the timer. The purpose of this tutorial is to create a quick and straight to the point customization to hide the timer in the execution screen. All other features, services and interfaces are left untouched.   As a big picture, here are the 6 modifications you will need to do: Modify the 4 mashups Modify 2 values in 2 tables of the MSSQL database   Status The mashup containing the timer is PTC.FSU.CWC.Execution.Overview_MU. It is easy to duplicate it and hide the timer widget (switch the visible property to false). But now, how to set it in the standard interface? In order to do it, you need to duplicate the mashups linked to the Execution.Overview_MU mashup. PTC.FSU.CWC.Execution.Overview_MU is directly referenced by the following entities: PTC.FSU.CWC.Authoring.Preview_MU PTC.FSU.CWC.Execution.WorkInstructionStart_MU PTC.FSU.CWC.GIobalUI.ApplicationSpecificHeader_HD PTC.FSU.CWC.WorkDefinitionExecution.StationSelectionContainer_EP   Customization Duplicate all those mashups except Authoring.Preview_MU because we will focus only on the authoring side of CWC. Hereafter it will be called the same as the original + _DUPLICATE. Perform the following modifications.   Open PTC.FSU.CWC.GlobalUI.ApplicationSpecificHeader_HD_DUPLICATE, then in Functions: open the expression named NavigateToStationSelection. Change the name of the mashup to the relevant one, example: PTC.FSU.CWC.WorkDefinitionExecution.StationSelectionContainer_EP_DUPLICATE open the validator named ShowRaiseHand. Change the name of the 2 mashups to the relevant ones, example: PTC.FSU.CWC.Execution.WorkInstructionStart_MU_DUPLICATE and PTC.FSU.CWC.Execution.Overview_MU_DUPLICATE open the validator named ShowStationSelection. Change the name of the 2 mashups to the relevant ones, example: PTC.FSU.CWC.Execution.WorkInstructionStart_MU_DUPLICATE   Open PTC.FSU.CWC.Execution.Overview_DUPLICATE, then in Functions: open the expression named SetMashupToWorkInstructionStart. Change the name of the mashup to the relevant one, example: PTC.FSU.CWC.Execution.WorkInstructionStart_MU_DUPLICATE open the expression named SetMashupToStationSelection. Change the name of the mashup to the relevant one, example: PTC.FSU.CWC.WorkDefinitionExecution.StationSelectionContainer_EP_DUPLICATE   Open PTC.FSU.CWC.Execution.WorkInstructionStart_MU_DUPLICATE, then in Functions: open the expression named NavigateToStart. Change the name of the mashup to the relevant one, example: PTC.FSU.CWC.Execution.Overview_MU_DUPLICATE open the expression named NavigateToStationSelection. Change the name of the mashup to the relevant one, example: PTC.FSU.CWC.WorkDefinitionExecution.StationSelectionContainer_EP_DUPLICATE   Open PTC.FSU.CWC.WorkDefinitionExecution.StationSelectionContainer_EP_DUPLICATE, in functions: open the expression named NavigateToStart. Change the name of the mashup to the relevant one, example: PTC.FSU.CWC.Execution.Overview_MU_DUPLICATE open the expression named NavigateToWorkInstructionStart. Change the name of the mashup to the relevant one, example: PTC.FSU.CWC.Execution.WorkInstructionStart_MU_DUPLICATE   Now, let’s change the database value. In MSSQL, navigate to the thingworxapps database, and edit the dbo.menu table. Look the line for AssemblyExecution (by default line 22) and look the value in column targetmashuplink. Switch the original value PTC.FSU.CWC.WorkDefinitionExecution.StationSelectionContainer_EP to the name of the duplication of this mashup. Lastly, edit the dbo.menucontext table. Look the line related to CWC (application UID = 5) and look the value in column targetmashuplink. Switch the original value PTC.FSU.CWC.GlobalUI.ApplicationSpecificHeader_HD to the name of the duplication of this mashup.   Result After this modification, you can start and check an operation. You should see the following result:
View full tip