how does the dashboard visualization connect to entity telemetry data - johnnyw-aws/aws-iot-twinmaker-samples GitHub Wiki
Telemetry data in TwinMaker is received through the GetPropertyValueHistory API. In this demo we're invoking this API using entity requests (for details on different kinds of GetPropertyValueHistory API requests, see our <docs>
). For entity requests, we query for specific telemetry data as identified by its (entity, component name, property name)
reference.
Physical assets are modeled in TwinMaker as entities, and their details (such as static properties, relationships with other entities, and time-series telemetry data properties) are modeled in components that are then attached to the entity. For deeper discussion of this topic see <docs / howto>
. Let's take a closer look at the entity model for the Freezer Tunnel [ref]:
...
{
"components": {
"CookieLineComponent": {
"componentTypeId": "com.example.cookiefactory.cookieline",
"properties": {
"alarm_key": {
...
},
"telemetryAssetId": {
...
},
"telemetryAssetType": {
...
}
}
},
"EquipmentComponent": {
"componentTypeId": "com.example.cookiefactory.equipment",
"properties": {
"belongTo": {
...
},
"feed": {
...
}
}
}
},
"description": "",
"entityId": "FREEZER_TUNNEL_c726a21e-8fd4-4210-b71e-0ef9acc59d97",
"entityName": "FREEZER_TUNNEL",
"parentEntityId": "COOKIE_LINE_1_70cde09c-2c2b-4aa2-9fc3-a91ff659e8f3"
},
...
We can see that it has 2 components: CookieLineComponent as defined by the componentTypeId com.example.cookiefactory.cookieline
and EquipmentComponent as defined by com.example.cookiefactory.equipment
. Let's take a closer look at the cookieline
component type definition <ref>
https://github.com/aws-samples/aws-iot-twinmaker-samples/blob/main/src/workspaces/cookiefactoryv2/tmdt_project/com.example.cookiefactory.cookieline.json
{
"componentTypeId": "com.example.cookiefactory.cookieline",
...
"functions": {
"dataReader": {
"implementedBy": {
"isNative": false,
"lambda": {
"arn": "__TO_FILL_IN_SYNTHETIC_DATA_ARN__"
}
},
"isInherited": true
}
},
...
"propertyDefinitions": {
...
"Speed": {
"dataType": {
"type": "DOUBLE"
},
"isExternalId": false,
"isFinal": false,
"isImported": false,
"isInherited": false,
"isRequiredInEntity": false,
"isStoredExternally": true,
"isTimeSeries": true
},
"Temperature": {
"dataType": {
"type": "DOUBLE"
},
"isExternalId": false,
"isFinal": false,
"isImported": false,
"isInherited": false,
"isRequiredInEntity": false,
"isStoredExternally": true,
"isTimeSeries": true
},
...
}
}
There are a number of fields defined in the model but for this discussion we'll focus on our data connectivity to the Temperature
data. This is defined as a property of the component type <ref:https://github.com/aws-samples/aws-iot-twinmaker-samples/blob/main/src/workspaces/cookiefactoryv2/tmdt_project/com.example.cookiefactory.cookieline.json#L59>
. We also define a dataReader
element which specifies the Lambda ARN to invoke to retrieve data for any entity with this component type attached to it.
With these entity model details (FreezerTunnel entity with CookieLine component with Temperature property and dataReader definition) we have the minimal entity model elements to connect to data. When the GetPropertyValueHistory API is invoked to fetch Temperature data for the FreezerTunnel, it will send a request to the Lambda with a request payload and expects the Lambda to return back a response payload containing the requested Temperature data.
Let's take a closer look at the sample Lambda used in this demo.
The Lambda used in this demo returns synthetic data back to the application but can be modified to fetch data from any datasource accessible by AWS Lambda. (e.g. for an example that connects to Timestream see <ref>
). Most of the request/response payload manipulation is handled by the udq_utils
helper library. For details on using this library to implement GetPropertyValueHistory (also sometimes referred to as "Unified Data Query (UDQ)") see <ref:udq_utils doc>
.
In summary, it consists of 3 main elements:
- Sample data json
<details on how we construct a pandas dataframe and why>
- Implementation of UDQ according to udq_utils
<details on _get_data_rows>
- Data extrapolation logic
<details + diagram>
With the above elements in mind, let's walk through a sample request to the Lambda:
When the GetPropertyValueHistory API is invoked with this AWS CLI command:
<sample cli command>
The Lambda receives this event payload:
<payload>
After the payload is processed by udq_utils
the entity_query
implementation hook is invoked and we use our _get_data_rows()
implementation to handle the request. Based on the selected_properties
in the request, we retrieve the relevant column from our pre-computed pandas dataframe and based on the request start and end times we calculate the offset into our sample telemetry data to start extrapolating data from. We iterate over the sample data repeatedly until we've generated enough response data and return the result as a list of RenderIoTTwinMakerDataRow objects.
<abbreviated objects - show for multi-prop if supported>
The udq_utils
library takes this data and appropriately transforms / groups it under entity-component-property references to constructs the final JSON response payload to return from the Lambda:
<response payload>
We then get the following result to our initial AWS CLI GetPropertyValueHistory API request:
<response payload>