I am trying to learn Thingworx by creating a simple end-to-end example:
IoTDevice --> POST gaugeValue(59) --> JSON/REST Thingworx --> Mashup --> GaugeWidget
For example, an IoT device does a POST of JSON data to a RESTful Thingworx service…
The JSON data contains a Value to be displayed in a Thingworx Mashup / Gauge Widget.
Question: what is the simplest way to connect a data value received in a Thingworx
Script to a Mashup / Widget?
I have done the following:
- Created a Thing called "SmartThing" in Composer.
- Created a Service called "RestListener" which accepts a "payload" with Type JSON.
- In the body of the RestListener script is just the following two lines:
logger.warn("Made it to the REST listener");
- I can issue a POST from an IoT device containing the following JSON:
- The POST is to:
- I can see in the Thingworx log both the logger.warn statements; the second contains the
correct value for gaugeValue...so the POST works and the script can read the data value.
- I created a Mashup... named it "SmartThing"
- I added a Panel and in the panel added a Gauge widget
- How do I connect the "gaugeValue" in my script to update "gauge-2" in my Mashup...
It seems like this should be simple...but I have spent hours trying with no success...
Thanks for listening...
You'll want to create a Thing (and best practice before that a ThingTemplate) with a Property to hold the Gauge Value
So let's say it's Pressure, you create a ThingTemplate with a Property called pressure. You also create that service in the Template
have that service write the value to the property
Now you can create any number of Things and your sensors can post to their matching Thing.
In the mashup you can now use service like GetProperties / GetPropertyValues
To extend this and scale this, you can first call a list of GetImplementingThings from your ThingTemplate and then use that in a List
then use the selection to drive the value retrieval of an individual Thing
You first probably want to edit your service to return the actual payload value. So change your result type to match whatever the value actually is and then set result=payload.datashape.fieldDinitions.guageValue;
In right panel within composer when you have your mashup open, click the little plus sign. When the window opens, search for your SmartThing thing then select your RestListener to add it to the service list.
Drag the AllData from the results section of your service to your widget and bind it to the data parameter.
You'll also probably want to add a refresh widget to your mashup since you've yet to construct your model to support the remote thing concept. Drag the refresh event from the refresh widget to your RestListener Service in the mashup builder so that when the refresh event fires it gets whatever value the RestListener service returns.
Thanks for the reply...
I've done the following:
- changed my RestListener definition to return a # NUMBER result
- added this code at the end of my RestListener:
var result = parseInt(payload.dataShape.fieldDefinitions.gaugeValue, 10);
- In the Mashup
- Added SmartThing to the service list
- Dragged # result to the Gauge
- Bound to # Data
- View Mashup still doesn't show any value for the gauge...pressed Refresh, etc...
- The logger messages indicate that the correct value is being assigned to "result"
Ahh...the Mashup Loaded Event! You need to click on the workspace tab, select Mashup, and then from the little arrow that appears in the top left of the workspace, click on it, selected the Loaded event and drag that over to your service. Now when the mashup loads, it will fire that service which should grab your data and update the gauge.
Thanks again for your reply...
It turns out that I can't have the Loaded or Refresh events invoke my RESTful Service directly...
It expects an input of JSON data... since the Loaded/Refresh events don't provide that, my Service reports an error.
I have tried the following as a workaround...
I create a Property "gaugeValue" in my Thing... type # NUMBER
In my RESTful Service handler, I update it like this:
Things["SmartThing"].gaugeValue = payload.dataShape.fieldDefinitions.gaugeValue;
I created a new Service named GetGaugeValue...
It returns a # NUMBER
var result = Things["SmartThing"].gaugeValue;
If I "test" this Service from the Composer, it gets the last value that was updated via the RESTful POST...
I then went back to my Mashup...
I removed the old wiring..
I wired the GetGaugeValue Service to my Gauge # Data
I added an "Auto Refresh" Widget and wired it to my Service
I wired the Mashup's Loaded event to the Service
I can see my logger.warn statements from the GetGauageValue Service periodically appearing in the log with the latest value...
so the Load/Refresh widget is working...
But...the Gauge still does not show any value...
Can I wire directly from a Service to a Widget?
When I "test" my service, I get an option to create a "DataShape"...do I need an intermediate DataShape?
Are you using the GetProperties or GetPropertyValues service to bring the Property values into your mashup? That's what I recommend as your remaining step.
And you can then also use the GetProperties Push When New Value received option