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

IoT Tech Tips

Sort by:
Hello Community Members! I am excited to join the ThingWorx Community as the newest member of the ThingWorx Product Management team. I come from product marketing here at PTC supporting our smart connected product solutions, so I am no stranger to ThingWorx.       Product management has been a goal and interest of mine for a few years now, and I am energized to be a part of the ThingWorx network and to get involved with this engaged community. Moving forward, I will be providing ThingWorx product release updates, spotlighting community members (connect with me if you are interested in being featured!), and answering any questions you may have on the ThingWorx platform. I will be known as @RachelMc on the Community, so look out for “The Truth About Things” and announcements coming soon. And, remember to keep monitoring the IoT Tech Tips page for updates from the broader PM team. I look forward to connecting with you all! -Rachel
View full tip
Based on Google's Spanner DB; CockroachDB is a distributed SQL DB scaling horizontally; surviving disk, machine, rack & even datacenter failures. It is built to automatically replicate, rebalance & recover with minimal configuration  See What is CockroachDB? for more.   Useful in use cases requiring: Distributed or replicated OLTP Multi-datacenter deployments Multi-region deployments Cloud migrations Cloud-native infrastructure initiatives Note: CockroachDB in current state isn't suitable for heavy analytics / OLAP.   Feature that makes it really attractive As mentioned above, scaling horizontally it requires minimal configuration out of the box allowing quick setup starting from local laptop/machine as shown below it can scale easily to single dedicated server, development/public cloud cluster. Due to easy setup, adding new nodes is as simple as starting the cockroach utility.See CockroachDB FAQ for more. To top it off, it uses PostgreSQL Wire protocol and PostgreSQL's dialect further reducing configuration and special JDBC driver requirements when a ThingWorx is configured with PostgreSQL as persistence provider.   Setting up cockroach DB cluster Download required binary or docker version from Install CockroachDB available for Mac, Linux & Windows   PS :Following setup uses Window's binary on a VM with Win10 64 bit, 6G RAM.     Starting Cluster node Open command prompt and navigate to the directory where cockroach.exe is unzipped, and launching the node with following command prompt     cockroach.exe start --insecure --host=10.128.13.183 --http-port=8082     This will start a node on defined host in insecure mode with its web based DB administration console on port 8082 and DB listening on default port 26257. Note it will log a security warning since node is started in insecure mode due to the tag --insecure, like so     * * WARNING: RUNNING IN INSECURE MODE! * * - Your cluster is open for any client that can access 10.128.13.183. * - Any user, even root, can log in without providing a password. * - Any user, connecting as root, can read or write any data in your cluster. * - There is no network encryption nor authentication, and thus no confidentiality. * * Check out how to secure your cluster: https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html * CockroachDB node starting at 2018-03-16 11:52:57.164925 +0000 UTC (took 2.1s) build: CCL v1.1.6 @ 2018/03/12 18:04:35 (go1.8.3) admin: http://10.128.13.183:8082 sql: postgresql://root@10.128.13.183:26257?application_name=cockroach&sslmode=disable logs: C:\CockroachDb\cockroach116\cockroach-data\cockroach-data\logs store[0]: path=C:\CockroachDb\cockroach116\cockroach-data\cockroach-data status: restarted pre-existing node clusterID: 012d011e-acef-47e2-b280-3efc39f2c6e7 nodeID: 1     Ensure that the secure mode is used when deploying in production.   Starting 2 additional nodes   Starting node2 cockroach.exe start --insecure --store=node2 --host=10.128.13.183 --port=28258 --http-port=8083 --join=10.128.13.183:26257   Starting node 3   cockroach.exe start --insecure --store=node2 --host=10.128.13.183 --port=28259 --http-port=8084 --join=10.128.13.183:26257     Note: Both of these 2 nodes are joining the cluster via 10.128.13.183:26257 (port for the node 1)   Verifying the live cluster and nodes via the web based CockroachDB admin console Open a web browser with any of the above node's http-port e.g. http://10.128.13.183:8084 Click on the View nodes list on the right panel   This will open the nodes list page   Connecting to ThingWorx as external datastore Good news, if your ThingWorx is running with PostgreSQL persistence provider, then no additional JDBC driver needed as CockroachDB uses the PostgreSQL wire protocol additionally, the SQL dialect is that of PostgreSQL For any other persistence provider download and install the PostgreSQL Relational Database Connector from ThingWorx Marketplace.   Creating a database in the cluster Start SQL client connecting to any of the running node, open a command prompt navigate to the directory containing cockroach.exe use following command:   cockroach sql --insecure --port=26257 This will change the prompt to root@<serverName/IP>:26257> Since above command logs in insecure mode no password is needed, default admin username is root in CockroachDb, use following to create a database   create database thingworx; show databases; root@10.128.13.183:26257/> SHOW databases; +--------------------+ | Database | +--------------------+ | crdb_internal | | information_schema | | pg_catalog | | system | | thingworx | | thingworxdatastore | +--------------------+ (6 rows)   This confirms thingworx database is created Creating a user to access that database CREATE USER cockroach WITH PASSWORD 'admin'; This will grant all rights to "cockroach" user on the database thingworx database   grant all on database thingworx to cockroach; Creating a Thing & connecting to CockroachDB via ThingWorx Composer For below example ThingWorx is using PostgreSQL as persistence provider. Create a Thing based of Database Thing Template Use following connection settings:   JDBC Driver Class Name : org.postgresql.Driver JDBC Connection String : jdbc:postgresql://<serverIp/name>:26257/thingworx?sslmode=disable Database User Name : cockroach Database password : <password>   Navigate to the Properties to verify the connectivity   Creating table(s) Now that the Thing is connected to the database, there are following ways DB objects can be created Via Thing based SQL Command Via SQL CockroachDB's SQL client Following command will create a small demo table CREATE TABLE demo ( id INT, demovalue STRING) Use SQLCommand as JavaScript handler when using above statement to create table directly from ThingWorx's Database Thing Verifying the Database & a table created within that DB via the web admin console of CockroachDb Under the left panel click on the Databases from the home page of one of the node's web admin consloe e.g. http://localhost:8084     Apart from other useful information about the database e.g. the database size and total number of tables, etc., clicking on the table name will also show the sql used to create it (including the defaults).   Creating couple of Database Thing services to perform bulk insert into the table from ThingWorx Composer Insert Service created as SQL Command with code snippet, service takes 2 inputs of type int and string   insert into demo values ([[id]], [[demoValue]]) JavaScript service executing bulk demo data insert by wrapping the SQL service created above   for (i=0; i<2000; i++) { var params = { id: i /* INTEGER */, demoValue: 'Insert from node 0 while node 3 is down' /* STRING */ }; // result: NUMBER var result = me.InsertDemo(params); }   At this point different users in ThingWorx with sufficient access rights can create their DB Things in ThingWorx Composer and can use any of the node address to read/write the data to the CockroachDB cluster. For the purpose of demo one node was stopped while other 2 were running and data was written to the clsuter via the test service created above. Once the 3rd node was restarted we can see the automatic replication happening between the nodes; this can be seen live via the web based admin console of any of the running node's web console.   As highlighted above at certain point in time after i.e 1500hrs all nodes were synced with the data, including the node3 ,which as mentioned above was down while data was being inserted to the cluster. All of the above replication process was done using default configuration.    
View full tip
This post is part of the series Forced Root Cause Monitoring via Mashups and Modal Popups To not feel lost or out of context, it's recommended to read the main post first. Create Entities   AlertStateDefinition   Create a new StateDefinition called "rcp_AlertStateDefinition" In the State Information tab, select Apply State: Numeric from the list on the right hand side Create a new State: Less than or equal to "1" Display Name: "Something good" Style: a new custom style with text color #f5b83d (orange) Create a new State: Less than or equal to "2" Display Name: "Something bad" Style: a new custom style with text color #f55c3d (red) Create a new State: Less than or equal to "3" Display Name: "Something ugly" Style: a new custom style with text color #ad1f1f (red) with a Font Bold Edit the "Default" State Set the Style: a new custom style with text color #36ad1f (green) We will not use this style, but in case we need a default configuration it will blend into the color schema Save the StateDefinition ValueStream   Create a new ValueStream called "rcp_ValueStream" (choose a default ValueStream, not a RemoteValueStream) Save the ValueStream AlertThing   Create a new Thing called "rcp_AlertThing" Based on a Generic Thing Base Thing Template Using the rcp_ValueStream Value Stream In the Properties and Alerts tab create the following Properties Name: "trigger" Base Type: BOOLEAN With a Default Value of "false" Check the "Persistent" checkbox Name: "selectedReason" BaseType: NUMBER Check the "Persistent" checkbox Check the "Logged" checkbox Advanced Settings: Data Change Type: ALWAYS In the Services tab create a new Service Name: "clearTrigger" No Inputs and no Outputs Service code me.trigger = false; When this service is executed, it will set the trigger Property to false Click Done to complete the Service creation Save the Thing    
View full tip
Hi i would like to insert my infotable data to QueryPropertyHistory service.   This is my data from my service.   My thing Properties:   My Value Stream Properties: My service code: var params = {     path: "k.csv" /* STRING */,     columnMappings:"date_trunc;People_in_region",     hasHeader: true /* BOOLEAN */,     dateFormat: "dd.MM.yyyy HH:mm" /* STRING */,     fileRepository: "SystemRepository",     fieldDelimiter: ";" /* STRING */,     stringDelimiter: "\"" /* STRING */,     dataShape: "TFPeopledata" /* DATASHAPENAME */ };   var result = Resources["CSVParserFunctions"].ReadCSVFile(params);   The problem is when I execute the generic service "QueryPropertyHistory", I get nothing as result.   Let's assume I collect Timeseries Data of two temperature sensors, located next to each other. This is done for redundancy and ensuring the quality of measures. Each of the sensors is logged into its Property in ThingWorx and I can create a Timeseries for the individual sensors. However I would like to create a combined InfoTable that holds information for both sensors, but averages out their values.   Instead of reading values from a stream, I just create some custom data for both InfoTables. After this I use the UNION function to combine the two tables and sort them. Once they are sorted, the INTERPOLATE function allows to group the InfoTable by timestamp.   With this, I have combined the two sensor result into on result set. Taking the average of numbers will give closer results to the real value (as both sensors might not be 100% accurate). In case one sensor does not have data for a given point in time, it will still be considered in the final output.   InfoTable1:   2018-12-18 00:00:00.000 2 2018-12-19 00:00:00.000 3 2018-12-20 00:00:00.000 5 2018-12-21 00:00:00.000 7   InfoTable2:   2018-12-18 00:00:00.000 1 2018-12-19 12:00:00.000 2 2018-12-20 00:00:00.000 3 2018-12-21 00:00:00.000 4   Combined Result:   2018-12-18 00:00:00.000 1.5 2018-12-19 00:00:00.000 3 2018-12-19 12:00:00.000 2 2018-12-20 00:00:00.000 4 2018-12-21 00:00:00.000 5.5     This can be done with the following code:   // Required DataShape "myInfoTableShape": "timestamp" = DATETIME, "value" = NUMBER // The Service Output is an InfoTable based on the same DataShape var params = { infoTableName : "InfoTable", dataShapeName : "myInfoTableShape" }; // Create two InfoTables, representing the data of each sensor var infoTable1 = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params); var infoTable2 = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params); var newEntry = new Object(); // Create custom data for InfoTable1 newEntry.timestamp = 1545091200000; newEntry.value = 2; infoTable1.AddRow(newEntry); newEntry.timestamp = 1545177600000; newEntry.value = 3; infoTable1.AddRow(newEntry); newEntry.timestamp = 1545264000000; newEntry.value = 5; infoTable1.AddRow(newEntry); newEntry.timestamp = 1545350400000; newEntry.value = 7; infoTable1.AddRow(newEntry); // Create custom data for InfoTable2 newEntry.timestamp = 1545091200000; newEntry.value = 1; infoTable2.AddRow(newEntry); newEntry.timestamp = 1545220800000; newEntry.value = 2; infoTable2.AddRow(newEntry); newEntry.timestamp = 1545264000000; newEntry.value = 3; infoTable2.AddRow(newEntry); newEntry.timestamp = 1545350400000; newEntry.value = 4; infoTable2.AddRow(newEntry); // Combine the two InfoTables via the UNION function var unionTable = Resources["InfoTableFunctions"].Union({ t1: infoTable1, t2: infoTable2 }); // Optional: Sort the table by timestamp var sortedTable = Resources["InfoTableFunctions"].Sort({ sortColumn: "timestamp", t: unionTable, ascending: true }); // Interpolate the (sorted) table by Interval and take average values and build the result var result = Resources["InfoTableFunctions"].Interpolate({ mode: "INTERVAL", timeColumn: "timestamp", t: sortedTable, ignoreMissingData: undefined, stats: "AVG", endDate: 1545609600000, columns: "value", count: undefined, startDate: 1545004800000 });      
View full tip
Disclaimer: The scripts and content published here are provided solely as a courtesy to PTC customers. Each script is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the PTC be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the scripts, including any software vulnerabilities.     Hi developers,   Ready to deploy ThingWorx containers on Kubernetes using Helm?   Let's get started using the steps below from Luis, one of our awesome software developers.   Before you dive too far in, please note that the following instructions assume you have downloaded the Docker scripts from our downloads portal and followed the instructions to build and publish the ThingWorx Docker images to your own Docker registry; they also assume that you have a working Kubernetes cluster with sufficient resources available.   These steps are intended to be used as a deployment manual and will not provide in-depth information about Kubernetes or the Helm package manager.     To start, you'll need the following prerequisites: A working Kubernetes cluster (Minikube should also work) kubectl cli tool installed and configured (https://kubernetes.io/docs/tasks/tools/install-kubectl/) helm cli tool installed and configured (https://docs.helm.sh/using_helm/#installing-helm)   In this example, we'll use the ThingWorx platform with PostgreSQL as a persistence provider. To prepare for the deployment, start by downloading the sample Helm chart  thingworx-0.1.0.tgz  (this is zipped in the .7z file attached ). You can take a look at what is configurable in this Helm chart: $ helm inspect thingworx-0.1.0.tgz This will show you the default configuration ( values.yaml ) and instructions ( README.md ) provided within the package. In the next steps, you'll see how to override some of these values to make the deployment fit your environment.    Let's create your custom  values  file. Use your favorite text editor and create a new file that looks like the following example. Please note the comments and make the necessary adjustments.    # Uncomment the following lines if you're using a private Docker registry that requires a username and password #imageCredentials: # password: mySecretAndSecurePassword # Your Docker Registry Password here # registry: docker.example.com # Your Docker Registry FQDN here # username: myUsername # Your Docker Registry Username here registry: domain: docker.example.com # Your Docker Registry FQDN here thingworx: image: repository: thingworx-platform-postgres # Your Thingworx Docker image name tag: 8.4.0 # Your Thingworx Docker image tag # Uncomment the following lines if you have the nginx-ingres addon installed on your cluster # ingress: # enabled: true # annotations: # kubernetes: # io/ingress: # class: nginx # hosts: # - twx.k8s.example.com # A FQDN that resolves to your cluster's ingress point   Note: The default  values.yaml  file included in the chart contains default usernames and passwords that must be changed before using this chart for production purposes. To change them also include a block like the following in your   myValues.yaml. postgresql: postgresPassword: YOUR_PG_ADMIN_PASSWORD commonConf: DATABASE_ADMIN_USERNAME: YOUR_PG_ADMIN_USER TWX_DATABASE_USERNAME: YOUR_TWX_DB_USER TWX_DATABASE_PASSWORD: YOUR_TWX_DB_PASSWORD RABBITMQ_USERNAME: YOUR_RABBITMQ_USER RABBITMQ_PASSWORD: YOUR_RABBITMQ_PASSWORD Save this file as  myValues.yaml .   If you have never used Helm with your cluster before, you should run the following command. This will install/upgrade the Helm server-side component (Tiller) on your Kubernetes cluster.   $ helm init --upgrade Now, to deploy ThingWorx, run the following command. This will deploy ThingWorx into your current kube config namespace. If you want to deploy into a specific namespace use the  --namespace  or  -n  flag.   $ helm upgrade --install -f myValues.yaml thingworx-test thingworx-0.1.0.tgz Wait a few seconds and you should have ThingWorx deployed onto your Kubernetes cluster. You can use  kubectl  to check if the ThingWorx and PostgreSQL pods are ready:   $ kubectl get pods If you have an Ingress set up on your cluster, you can just open a browser and point it to the URL you created for it; if not, you can use  kubectl  to reach it:   $ kubectl port-forward service/thingworx-test-twx 8080   Leave the terminal open and point your browser to http://localhost:8080/Thingworx.   Below, you can find an example using Minikube; you can get Minikube from https://github.com/kubernetes/minikube: # Start minikube minikube start --memory 8192 --cpus 4 # Set docker env so you can use local images with minikube eval $(minikube docker-env) # Ensure that kubectl is configured for minikube minikube update-context # Pull the image from your Docker registry docker pull artifactory.rd2.thingworx.io/twxdevops/tw-platform-postgres:8.4.0-build-latest # check the Thingworx helm default values and README helm inspect thingworx-0.1.0.tgz # Create your custom values file cat << EOF > myValues.yaml # Add the content registry: domain: artifactory.rd2.thingworx.io thingworx: image: repository: twxdevops/tw-platform-postgres tag: 8.4.0-build-latest pullPolicy: IfNotPresent # this is to use the existing local image in minikube resources: requests: cpu: 1 memory: 1Gi # Make sure it can fit our Minikube VM EOF # Initialize helm and tiller helm init --upgrade # Deploy Thingworx helm upgrade --install -f myValues.yaml thingworx-test thingworx-0.1.0.tgz # Verify the deployment status helm ls # Verify that the Thingworx and PostgreSQL pods where created (check the status column) kubectl get pods # Wait until both pods are ready and use kubectl port-forward to reach the Thingworx Composer UI kubectl port-forward service/thingworx-test-twx 8080 # Open the Thingworx Composer UI in your default browser xdg-open http://localhost:8080/Thingworx # Use open instead of xdg-open if you're on macOS Here's a quick video explaining the deployment of ThingWorx Docker images on Minikube.   (view in My Videos)   Let me know your thoughts and questions below!   Stay connected, Kaya  
View full tip