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

Community Tip - You can subscribe to a forum, label or individual post and receive email notifications when someone posts a new topic or reply. Learn more! X

IoT Tips

Sort by:
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
Previous Posts Widget Extensions Introduction Widget Extensions Click Event Widget Extensions Date Picker I was asked was it possible to make the Google Maps indicator bounce if a property was set to true. The answer is yes. Open up the google maps extension and locate the googlemap.ide.js Make the above changes. Open up the googlemap.runtime.js and search for if (showMarkers) { after the if add the following below Make sure you have a property needsAttension on a returned Thing. If the value is true it will bounce! After viewing Mashup there are 4 locations but one needs attention.
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
Key Functional Highlights ThingWorx Manufacturing Apps enhancements Support for NI InsightCM connected to KEPServerEX as an aggregator Controls Advisor usability improvement to retrieve App Key for a specific KEPServerEX connection Asset Advisor usability improvement for displaying alerts 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) Documentation ThingWorx Manufacturing Apps Setup and Configuration Guide ThingWorx Manufacturing Apps Customization Guide What’s New in ThingWorx Manufacturing Apps 8.1.0 Download Extensions for ThingWorx Manufacturing Apps and Asset Remoting Note: this release announcement applies to the ThingWorx Manufacturing Apps Extensions 8.1.0. For the ThingWorx Manufacturing Apps Freemium (Express) 8.1.0 release notes, see this page: ThingWorx Manufacturing Apps 8.1 Freemium is Available for Download!
View full tip
Introduction to the platform extensibility structures and options. Includes overview of setting up the eclipse plugin and build process, as well as install considerations and best practices.     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
This Expert Session reviews the concept of “Decision Trees” and the functionality that is available in ThingWorx Analytics Builder. First, you will learn how to create and upload a dataset in ThingWorx Analytics Builder.  After that, it shows you how to train a model and score on the model that was just generated. It then goes into detail on how the prediction learner "Decision Tree" operates and classifies inputs.     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
ThingWorx's JDBC extensions - Relational Database Management System and the JDBC Extensions allow ThingWorx to connect to variety of different databases. With that comes a natural question how and what sort of SQL statements could be executed via these extensions? Note: ​​Importing the JDBC extensions i.e. the RDBMS and JDBC Extensions, creates a Database Template for that particular database. If you are working with RDBMS extension then Template of corresponding Database will be created with similar name e.g. importing the RDBMS Extension for Oracle 12 will create Template named OracleDBServer12. While importing the JDBC driver using the JDBC extension will create Template name based on the JDBC driver used or a custom name could be given. Following examples and SQL statements are adhering to Oracle's SQL*Plus standard, however these can be easily adapted to the type of RDBMS you intend to work with. Topics How to create SQL Service in ThingWorx entity Types of SQL Statements Examples on SQL Service usage and some extended use cases / examples How to create SQL Service in ThingWorx Navigate to the Thing implementing the Database Template, e.g. OracleDBServer12         2. Click on the Services section under the Entity Information and click on Add My Service         3. A new service creation section will come up, change the Service type of JavaScript (this is default selection) to either SQL (Query) or SQL (Command) depending on the type of SQL you are to create under this particular service                       4. Here's quick example on creating SQL (Query) service which takes name as input for a select *  sql … Statement, i.e. it returns complete set of rows and columns from any given table on which the user has the access to perform Select                   Note: BaseType defaults to Infotable when creating SQL (Query) service and the returned number of rows are restricted to 500. Therefore, if table contains rows more than 500, ensure to change the Max Rows parameters         5. Example on creating SQL (Command) service that delete all the rows from the database table               Note: The Base Type defaults to Number when using SQL (Command)     Additional information:     When creating a SQL service, apart from providing changing the Service Info and  Inputs /Outputs, 3rd section Tables/Columns allows users to explore the Tables and their respective columns as part of that particular user's schema - meaning the objects on which the user has select rights in his schema in the database.     Types of SQLs This is not an exhaustive list, rather contains most commonly used types of SQL statements     1. Data Definition Language (DDL)           a. Create, Alter and drop schema objects           b. Grant and Revoke privileges and roles     2. Data Manipulation Language (DML)           a. Insert           b. Delete           c. Select Examples for SQL Service usage and some extended use cases / examples     1. Data Definition Language (DDL)           a. Create statement                       b. Alter statements                         c. Drop statement                         d. Flashback statements (Oracle specific)                         e. Grant statement                     f. Rename statement                 2. Data Manipulation Language (DML)           a. Insert statement                     b. Delete statement                     c. Select statements           Use cases - Case 1 : Backing up DataTable DataTable objects in ThingWorx are for quick lookup of data and they are most performant till ~100K rows. Exceeding rows over 100K in a DataTable makes it highly susceptible to performance issues in terms of querying or writing to it. Unless, there's sharding​ on the persistence provider or multiple persistence providers used - JDBC connectivity to external data stores like RDBMS systems could help in keeping up with growing number of rows in DataTables. RDBMS tables are more than capable of storing very large amount of rows without being taxed over the performance. JDBC extension could be used to do just that in a use case requiring backing up DataTable or any Data Storage objects from ThingWorx for that matter. Here's one quick example using one of the Insert SQL service shown above to back up the entire DataTable to the Oracle's DB table. Following ThingWorx JavaScript service wraps the InsertIntoBULKDATAINSERTDT SQL service: // result: INTEGER // getting total row count in the DataTable var totalCount = Things["BulkInsertDT"].GetDataTableEntryCount(); var params = { maxItems: totalCount /* NUMBER */ }; // result: INFOTABLE // DataTable service to fetch all the rows from it var allData = Things["BulkInsertDT"].GetDataTableEntries(params); // looping over the result fetched above to get all the rows for insertion     for (var i = 0; i<totalCount; i++) {         var result = allData.getRow(i); // mapping the data for insert     var params = {         LongCol3: result.LongCol3 /* LONG */,         numcol1: result.NumCol1 /* NUMBER */,         StringCol2: result.StringCol2 /* STRING */,         IntCol4: result.IntCol4 /* INTEGER */     }; try { // result: NUMBER // calling the SQL Service InsertIntoBULKDATAINSERTDT created under a DB Thing called OracleDBThingNew     var result = Things["OracleDBThingNew"].InsertIntoBULKDATAINSERTDT(params); } catch (err) {      Logger.info ("Failed to insert the values" + err) }     }
View full tip
Key Functional Highlights Production Advisor is now available in the Freemium and Developer Kit downloads. Plant Managers are provided with real-time monitoring of production status and critical KPI’s such as utilization, performance, quality and OEE, by unifying data from disparate lines, assets and sensors. With Production Advisor, Plant Managers have the ability to detect and react instantly to production issues- reaching lower downtime, higher production throughput and better quality from the factory resources. Compatibility ThingWorx 8.0.1 KEPServerEX 6.2 KEPServerEX V6,1 and older as well as different OPC Servers (with Kepware OPC aggregator) Documentation ThingWorx Manufacturing Apps Setup and Configuration Guide: https://support.ptc.com/WCMS/files/173133/en/ThingWorxManufacturingAppsSetup_8-0-1.pdf ThingWorx Manufacturing Apps Customization Guide: https://support.ptc.com/WCMS/files/173135/en/ThingWorxManufacturingAppsCust_8-0-1.pdf Get Started Documentation on Portal: https://www.ptc.com/en/thingworx/manufacturing-apps/Dashboard/Get-Started (PTC users should use their normal login credentials and do not need to register on the portal) Download Freemium and Developer Kit (8.0.1) are available for download here: https://www.ptc.com/en/thingworx/manufacturing-apps/Dashboard (PTC users should use their normal login credentials and do not need to register on the portal ThingWorx Platform Extensions (8.1.0, released 1 Nov 2017) are available for download here: https://support.ptc.com/appserver/auth/it/esd/product.jsp?prodFamily=TWA
View full tip
Check out this new KCS article which links to all known best practice documents available for ThingWorx. This article will get larger in time as more articles are published related to the Dos and Don'ts of building an IoT application! Do you know when to use timers, and where to implement their subscriptions? How about ensuring info tables are used at the proper time, and data tables at others? Pesky performance issues wherein ThingWorx runs slow for apparently no reason? All of these questions and more are addressed here!
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
Connecting Existing Things to ThingWorx Industrial Gateway for Anomaly Detection   In this Video you will learn how to :   - To bind a property of an existing entity to the KEPSserverEX Data Feed - To create an Alert on that property and monitor it's behavior   Updated Link for access to this video:  Connecting Existing Things to ThingWorx Industrial Gateway for Anomaly Detection
View full tip
When you install Thingworx with PostgreSQL, you can't import the "PostgreSQL" extension because of the conflict of a library file. So, here is a sample "MetaData.xml" file. You can zip this file and simply import it into your Thingworx so that you can have a thing template for "PostgreSQL" database. <Entities>     <ExtensionPackages>         <ExtensionPackage name="PostgreSQL_ExtensionPackage"                       description="PostgreSQL JDBC Extension"                       vendor="ThingWorx Customer Service"                       packageVersion="1.0"                       minimumThingWorxVersion="4.0.0">         </ExtensionPackage>     </ExtensionPackages>     <ThingTemplates>         <ThingTemplate baseThingTemplate="Database" description="PostgreSQL Server" documentationContent="" effectiveThingPackage="" homeMashup="" lastModifiedDate="2015-11-28T11:40:35.355-05:00" name="PostgreSqlServer" tags="" thingPackage="">             <ThingShape description="" documentationContent="" lastModifiedDate="2015-11-28T11:40:35.355-05:00" name="" tags="">                 <PropertyDefinitions/>                 <ServiceDefinitions/>                 <EventDefinitions/>                 <ServiceImplementations/>                 <ServiceMappings/>                 <Subscriptions/>             </ThingShape>             <ImplementedShapes/>             <ConfigurationTables>                 <ConfigurationTable description="" isMultiRow="false" name="ConnectionInfo">                     <DataShape>                         <FieldDefinitions>                             <FieldDefinition aspect.defaultValue="5.0" baseType="NUMBER" description="Maximum number of connections in the pool" name="maxConnections" ordinal="0"/>                             <FieldDefinition aspect.defaultValue="jdbc" baseType="STRING" description="jDBCConnectionURL" name="jDBCConnectionURL" ordinal="0"/>                             <FieldDefinition aspect.defaultValue="SELECT NOW()" baseType="STRING" description="Connection validation string" name="connectionValidationString" ordinal="0"/>                             <FieldDefinition aspect.defaultValue="org.postgresql.Driver" baseType="STRING" description="jDBCDriverClass" name="jDBCDriverClass" ordinal="0"/>                             <FieldDefinition baseType="STRING" description="Database user name" name="userName" ordinal="0"/>                             <FieldDefinition baseType="PASSWORD" description="Database password" name="password" ordinal="0"/>                         </FieldDefinitions>                     </DataShape>                     <Rows>                         <Row>                             <jDBCConnectionURL><![CDATA[jdbc:postgresql://localhost:5432/demo]]></jDBCConnectionURL>                             <maxConnections>100.0</maxConnections>                             <connectionValidationString><![CDATA[SELECT NOW()]]></connectionValidationString>                             <jDBCDriverClass><![CDATA[org.postgresql.Driver]]></jDBCDriverClass>                             <userName />                             <password />                         </Row>                     </Rows>                 </ConfigurationTable>                 <ConfigurationTable description="" isMultiRow="false" name="ConnectionMonitoring">                     <DataShape>                         <FieldDefinitions>                             <FieldDefinition aspect.defaultValue="1.0" baseType="NUMBER" description="Number of retries" name="numberOfRetries" ordinal="0"/>                             <FieldDefinition aspect.defaultValue="2000.0" baseType="NUMBER" description="Retry delay in milliseconds" name="retryDelay" ordinal="0"/>                             <FieldDefinition aspect.defaultValue="false" baseType="BOOLEAN" description="Enable connection monitoring" name="enableMonitor" ordinal="0"/>                             <FieldDefinition aspect.defaultValue="30000.0" baseType="NUMBER" description="Monitor rate in milliseconds" name="connectionMonitorRate" ordinal="0"/>                         </FieldDefinitions>                     </DataShape>                     <Rows>                         <Row>                             <numberOfRetries>1.0</numberOfRetries>                             <retryDelay>2000.0</retryDelay>                             <enableMonitor>false</enableMonitor>                             <connectionMonitorRate>3000.0</connectionMonitorRate>                         </Row>                     </Rows>                 </ConfigurationTable>             </ConfigurationTables>             <avatar/>             <DesignTimePermissions>                 <Create/>                 <Read/>                 <Update/>                 <Delete/>                 <Metadata/>             </DesignTimePermissions>             <RunTimePermissions/>             <InstanceDesignTimePermissions>                 <Create/>                 <Read/>                 <Update/>                 <Delete/>                 <Metadata/>             </InstanceDesignTimePermissions>             <InstanceRunTimePermissions/>         </ThingTemplate>     </ThingTemplates> </Entities>
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
If you ever tested mashup rendering on mobile phones, you probably experienced that the mashup was not sizing to fit your mobile display. This "MobileHeader" extension enables to auto adapt the mashup to mobile displays.   It adds the following parameters to the HTML header: <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">   In the composer just drop the "MobileHeader" extension into a section of the mashup.   This extension was tested until version 7.4.
View full tip
Twilio extends the ThingWorx functionality to send SMS and voice messages in variety of languages. Starting from scratch I'll cover the steps required to setup the Twilio extension and the basic account registration (trial version) and setup at Twilio.com Twilio allows registering with the trial account, which comes with $15 as initial account balance, something which is quite useful for testing the initial setup and testing of Twilio extension in conjunction to ThingWorx. Prerequisite 1. Sign up, if not already done, with Twilio.com for free trail account 2. Configure the account to setup a verified phone number to receive text and voice messages, free trial account allows setting up 1 verified phone number that can receive text and voice messages Note: See What's the difference between a verified phone number and a Twilio phone number? 3. Choose and configure a Twilio phone number capable of sending text and voice messages, free trial account allows setting up of 1 Twilio number which will be used in the Extension configuration in ThingWorx for sending the messages 4. Download Twilio Extension from ThingWorx Marketplace Note that Twilio phone number should be enabled with the send SMS or send voice message capability, depending on what your use case is. Failing to do so will lead to error while testing the sendSMS or sendVOICE service (two default services provided with the Twilio Extension when imported in ThingWorx) Signing up and setting up Twilio account 1. Sign up on Twilio.com with your details and emailID. When registering for the first time you'll be prompted for your personal phone number as part of the security requirement. Also with free trial account this will be the only phone number where you'll be able to send SMS or Voice message via Twilio Extension in ThingWorx 2. Next would be to setup the Twilio number with voice and text messaging, navigate to https://www.twilio.com/console/phone-numbers/getting-started 3. Do ensure that you setup the voice or text capabilities for the new Twilio number, failing to do so will lead to error in sending message via Twilio Extension in ThingWorx 4. Different Twilio Number have different capabilities, it's quite possible that you don't find the number with required capabilities i.e. Voice, SMS - in that scenario simply search for different number, one that has the capabilities you are looking for 5. With trial account only 1 Twilio number is avilable for setup 6. While setting up the Twilio number you will be required to provide a valid local address of your country The cost of setting up the number and further sending the SMS will only be deducted from the $15 made available when you signed up for the first time. Navigate to your account details on Twilio.com to make note of the following information which will be used when configuring the Twilio Extension in ThingWorx: a. Account SID b. Authentication ID c. Your Verified Phone Number (will be used for receiving the messages) d. Twilio Phone number created with required capabilities, e.g. that number is capable of sending text message Here's how it shows up once you are successfully registered and logged on to the twilio.com/console To check your Twilio Phone Number and the Verified Phone Number navigate to twilio.com/phone-numbers As it can be seen in the above screenshot, the number I have bought from Twilio is capable of sending Voice and SMS. With this all's set  and ready to configure the Twilio Extension in ThingWorx, which is pretty straight forward. Setup Twilio Extension in ThingWorx 1. Let's setup the extension by navigating to the ThingWorx Composer > Import/Export > Extensions > Import > browse to the location where you saved the Twilio Extension from ThingWorx Marketplace and click Import 2. Once imported successfully refresh the composer and navigate to Modeling > Things , to create a new Thing implementing the Twilio Template (imported with the extension) like so, in screenshot below Thing is named DemoTwilioThing 3. Navigate to the the Configuration section of that Thing, to provide the information we noted above from Twilio account Note: this demo thing is setup to send the text SMS to my verified phone number only, therefore the CallerID in the configuration above is the Twilio number I created after signing up on Twilio with text message capability. 4. Save the created the Thing 5. Finally, we can test with the 1 of the 2 default services provided with the Twilio Template i.e. SendSMSMessage service 6. While testing the SendSMSMessage service use your verified phone number in To for receiving the message Troubleshooting some setup related issues I'll try to cover some of the generic errors that came up while doing this whole setup with Twilio Extension Error making outgoing SMS: 404 / TwilioResponse 20404 Reason If the Twilio number is not enabled with SMS sending capabilities you may run into such an error when testing the service. Here's the full error stack Unable to Invoke Service SendSMSMessage on DemoTwilioThing : Error making outgoing SMS: 404 <?xml version='1.0' encoding='UTF-8'?><TwilioResponse><RestException><Code>20404</Code><Message>The requested resource /2010-04-01/Accounts/<AccountSID>/SMS/Messages was not found</Message><MoreInfo>https://www.twilio.com/docs/errors/20404</MoreInfo><Status>404</Status></RestException></TwilioResponse> Resolution Navigate back to the Phone Number section on Twilio's website and as highlight in screenshot above check if the Twilio number is enabled with SMS capabilities. Error making outgoing SMS:400 / TwilioResponse 21608 Reason You may encounter following error when attempting to send SMS/Voice message, here's the full error detail Wrapped java.lang.Exception: Error making outgoing SMS: 400 <?xml version='1.0' encoding='UTF-8'?><TwilioResponse><RestException><Code>21608</Code><Message>The number <somePhoneNumber>is unverified. Trial accounts cannot send messages to unverified numbers; verify <somePhoneNumber>at twilio.com/user/account/phone-numbers/verified, or purchase a Twilio number to send messages to unverified numbers.</Message><MoreInfo>https://www.twilio.com/docs/errors/21608</MoreInfo><Status>400</Status></RestException></TwilioResponse> Cause: Error making outgoing SMS: 400 <?xml version='1.0' encoding='UTF-8'?><TwilioResponse><RestException><Code>21608</Code><Message>The number <somePhoneNUmber>is unverified. Trial accounts cannot send messages to unverified numbers; verify <somePhoneNumber> at twilio.com/user/account/phone-numbers/verified, or purchase a Twilio number to send messages to unverified numbers.</Message><MoreInfo>https://www.twilio.com/docs/errors/21608</MoreInfo><Status>400</Status></RestException></TwilioResponse> Resolution As the error points out clearly the number used in To section while testing the SendSMSMessage service didn't have verified number. With free trial account you can only use the registered verified phone number where SMS/Voice message can be sent. If you want to use different number an account upgrade is required. Error making outgoing SMS:400 / TwilioResponse 21606 Reason Following error is thrown while testing SendSMSMessage service with different Twilio number which is either not the same as the number you bought when setting up the trial account or it doesn have SMS sending capabiltiy. Here's the full error stack Wrapped java.lang.Exception: Error making outgoing SMS: 400 <?xml version='1.0' encoding='UTF-8'?><TwilioResponse><RestException><Code>21606</Code><Message>The From phone number <TwilioNumber>is not a valid, SMS-capable inbound phone number or short code for your account.</Message><MoreInfo>https://www.twilio.com/docs/errors/21606</MoreInfo><Status>400</Status></RestException></TwilioResponse> Cause: Error making outgoing SMS: 400 <?xml version='1.0' encoding='UTF-8'?><TwilioResponse><RestException><Code>21606</Code><Message>The From phone number <TwilioNumber> is not a valid, SMS-capable inbound phone number or short code for your account.</Message><MoreInfo>https://www.twilio.com/docs/errors/21606</MoreInfo><Status>400</Status></RestException></TwilioResponse> Resolution Check the configuration in the ThingWorx Composer for the Thing created out of Twilio Template whether or not the callerID is configured with correct Twilio account number
View full tip
Here is a demo that uses repeater widget and smart grid widget to display a nested table. Note: This demo is for testing use. Create a datashape for  the nested datatable named DataTableStructure Create DataShape named InfoStructure for Obj Create the nested datatable named DataTableTest as below Create a service named AddObjInput as below in this datatable Crate a Mashup named RepeaterMsh Add widgets like textbox, label, button and smart grid on the mashup There are some parameters we added before, please bind them to the widgets that we just added to the mashup Add DataTableTest service AddOrUpdateDataTableEntry to the mashup. Bind textbox and smart grid edited table to AddOrUpdateDataTableEntry parameter. Bind button click event to trigger the service AddOrUpdateDataTableEntry The smart grid widget need a special attribute named TableDefinition This demo sample is{"columns":[{"name":"PrimarySchool","type":"text","display":"PrimarySchool"},{"name":"SecondarySchool","type":"text","display":"SecondarySchool"},{"name":"HighSchool","type":"text","display":"HighSchool"}]} Create mashup which has repeater widgets The mashup over view is like below The first part is aimed to add a new record, the second part (repeater widget)is aimed to display table data, and also update data. In the first part, there are textboxs, labels, smart grid and button widget. They are banded to the service named AddDataTableEntry, aimed to add a new record in the table. (Smart grid is used to add the nested table data) There is a button named AddRecords, bind it’s clicked event to AddDataTableEntry service. And bind the AddDataTableEntry service’s event ServiceInvokeCompleteted to GetDataTableEntries The smart grid widget in here is an empty grid, but it should have a structure at beginning. That’s why to create a service named AddObjInput in step2. It returns an empty table but with the datashape. The second part is a repeater widget. Repeater widget has an attribute named Mashup, bind the mashup Repeatermsh. Bind GetDataTableEntries all data to the repeater widget. There should be some parameters that need to bind like gender, InfoTable, Sname… Testing the demo Note: Smart Grid widget is not a ThingWorx OOTB functionality The smart grid widget can be edited flexible. Please download with is Link https://marketplace.thingworx.com/Items/Smart%20Grid%20Widget There is a thread teach how to use smart grid: https://community.thingworx.com/message/53379#53379
View full tip
Hello! I have just written a tutorial on how to set up Lua to be run from the command line. As many already know, there is no good way to debug Lua scripts as they are used in package deployment in Software Content Manager, and building such a debugger is a vast and difficult undertaking. As an alternative, running small portions of code in the command line to ensure they will work as expected is one way to verify the validity of the Lua syntax prior to attempting a deployment. Here are the steps to set up Lua as a command line tool:   Grab the GCC compiler called TDM-GCC Run the exe file and follow the install instructions Remember the install directory for this, as the attached install script will need to be configured in a later step Default location in the install file is "C:\Program Files\TDM-GCC\" Note: leaving the "Add to PATH" selected will allow you to compile C code on the command line as well by typing "gcc" (this is not required for this set-up) Download the Lua source code ​This comes as a ".tar.gz" file, which can be tricky to extract in Windows Download 7zip for freeware which can unzip this type of archive Extract the Lua source code and navigate to the top level directory which should just contain one folder named like "lua-x.x.x" where the x's refer to the version Download and extract the attached zip file containing the build file Copy the "build.cmd" file from this to the top level directory of the Lua source code Modify the configuration as needed: Version number default is 5.3.4 (parameter is called lua_version) GCC install path default is "C:\Program Files\TDM-GCC\bin" (parameter is called lua_build_dir) Double click the "build.cmd" file A console window will appear with installation details If you see the following, then it worked successfully: The "lua\" directory will be created in the same folder as the "build.cmd" file Copy the "lua\" directory to "C:\Program Files\" Open "Computer" > "System Properties" > "Advanced system settings" Click "Environment Variables" > "New..." Call the variable "LUA" and make the value "C:\Program Files\lua\bin" Find the "Path" variable and click "Edit..." At the end of what is already there (do NOT delete anything that is already there), add "%LUA%" (make sure there is a ";" between the previous path and this entry) Click "Ok" Open a new command prompt (has to be new to load the new path) and type "lua" to see if it works Example syntax test from Lua command line:   I hope this is helpful to people! Let me know if you have any questions!
View full tip
This video is the 2nd part, of a series of two videos, walking you through the configuration of Analysis Event which is applied for Real-Time Scoring. This part 2 video will walk you through the configuration of Analysis Event for Real-Time Scoring, and validate that a predictions job has been executed based on new input data.   Updated Link for access to this video:  Analytics Manger 7.4: Configure Analysis Event & Real Time Scoring Part 2 of 2
View full tip
This video walks you through the use of Analysis Replay to execute analysis events on historic data. This video applies to ThingWorx Analytics 7.4 to 8.1   Updated Link for access to this video:  Analytics Manager : Using Analysis Replay
View full tip
Announcements