Asset Management Service – Modeling Assets¶
This example illustrates how assets can be modeled and structured. In this example a global wind power company, which has multiple wind farms around the globe, creates their first assets in Insights Hub. For more information on the endpoints used in the example, refer to the API specification.
The company has one type of wind turbines, the WindTurbine1000
, from which the following electrical and mechanical metrics are to be collected:
- Power output in MW
- Voltage
- Rotations per minutes in RPM
- Vibrations of rotors in Hz
The company has wind farms installed in the North Sea and the Baltic Sea. For each wind farm, two assets shall be created.
Wind Farm North Sea | Wind Farm Baltic Sea | |
---|---|---|
GPS coordinates | 54.008333, 6.598333 | 54.834, 14.068 |
Turbine #1 | N-001 | B-001 |
Turbine #2 | N-002 | B-002 |
Prerequisites¶
- You have access to a Insights Hub tenant
- You have the
mdsp:core:assetmanagement.admin
role
Preparing Templates¶
Creating Aspect Types¶
Two aspect types shall be created, one for electrical metrics and the other for mechanical metrics. This is done using the endpoint:
PUT /aspecttypes/{id}
For the aspect type for electrical metrics, the {id}
is named {tenantId}.ElectricalMetrics
and the body of the request is:
{
"name": "ElectricalMetrics",
"category": "dynamic",
"scope": "private",
"description": "Electrical metrics for wind turbines",
"variables": [
{
"name": "PWR_OUT",
"dataType": "DOUBLE",
"unit": "MW",
"qualityCode": true,
"searchable" : true
},
{
"name": "V_OUT",
"dataType": "DOUBLE",
"unit": "Volt",
"qualityCode": true,
"searchable" : true
}
]
}
The result can be verified by checking the response:
{
"id": "{tenantId}.ElectricalMetrics",
"tenantId": "{tenantId}",
"name": "ElectricalMetrics",
"category": "dynamic",
"scope": "private",
"description": "Electrical metrics for wind turbines",
"variables": [
{
"name": "PWR_OUT",
"unit": "MW",
"searchable": true,
"qualityCode": true,
"defaultValue": null,
"dataType": "DOUBLE",
"length": null
},
{
"name": "V_OUT",
"unit": "Volt",
"searchable": true,
"qualityCode": true,
"defaultValue": null,
"dataType": "DOUBLE",
"length": null
}
],
"etag": {etagvalue},
"_links": {
"self": {
"href": "{link}"
}
}
}
For the aspect type for mechanical metrics, the {id}
is named {tenantId}.MechanicalMetrics
and the body of the request is:
{
"name": "MechanicalMetrics",
"category": "dynamic",
"scope": "private",
"description": "Mechanical metrics for wind turbines",
"variables": [
{
"name": "V",
"dataType": "INT",
"unit": "RPM",
"qualityCode": true,
"searchable" : true
},
{
"name": "VIB",
"dataType": "INT",
"unit": "Hz",
"qualityCode": true,
"searchable" : true
}
]
}
The created aspect type can be verified by checking the response:
{
"id": "{tenantId}.MechanicalMetrics",
"tenantId": "{tenantId}",
"name": "MechanicalMetrics",
"category": "dynamic",
"scope": "private",
"description": "Mechanical metrics for wind turbines",
"variables": [
{
"name": "V",
"unit": "RPM",
"searchable": true,
"qualityCode": true,
"defaultValue": null,
"dataType": "INT",
"length": null
},
{
"name": "VIB",
"unit": "Hz",
"searchable": true,
"qualityCode": true,
"defaultValue": null,
"dataType": "INT",
"length": null
}
],
"etag": {etagValue},
"_links": {
"self": {
"href": "{link}"
}
}
}
Creating Asset Types¶
After creating the required aspect types, the asset type for the WindTurbine1000
can be created using the following endpoint:
PUT /assettypes/{id}
Here, the {id}
is named {tenantId}.WT1000
and the body of the request is:
{
"name": "WindTurbine 1000",
"description": "WindTurbine 1000 with best reliability.",
"parentTypeId": "core.basicdevice",
"instantiable": true,
"scope": "private",
"variables": [
{
"name": "InstallationDate",
"dataType": "TIMESTAMP",
"searchable": true,
"defaultValue": "1970-01-01T09:00:00+00:00"
}
],
"aspects": [
{
"name": "ElectricalMetrics",
"aspectTypeId": "{tenantId}.ElectricalMetrics"
},
{
"name": "MechanicalMetrics",
"aspectTypeId": "{tenantId}.MechanicalMetrics"
}
]
}
The created asset type can be verified by checking the response:
{
"parentTypeId": "core.basicdevice",
"instantiable": true,
"tenantId": "{tenantId}",
"name": "WindTurbine 1000",
"description": "WindTurbine 1000 with best reliability.",
"scope": "private",
"variables": [
{
"name": "InstallationDate",
"unit": null,
"searchable": true,
"defaultValue": "1970-01-01T09:00:00+00:00",
"dataType": "TIMESTAMP",
"length": null
}
],
"aspects": [
{
"name": "ElectricalMetrics",
"aspectType": {
"id": "{tenantId}.ElectricalMetrics",
"tenantId": "{tenantId}",
"name": "ElectricalMetrics",
"category": "dynamic",
"scope": "private",
"description": "Electrical metrics for wind turbines",
"variables": [
{
"name": "PWR_OUT",
"unit": "MW",
"searchable": true,
"qualityCode": true,
"defaultValue": null,
"dataType": "DOUBLE",
"length": null
},
{
"name": "V_OUT",
"unit": "Volt",
"searchable": true,
"qualityCode": true,
"defaultValue": null,
"dataType": "DOUBLE",
"length": null
}
],
"etag": {etagValue},
"_links": {
"self": {
"href": "{link}"
}
}
}
},
{
"name": "MechanicalMetrics",
"aspectType": {
"id": "{tenantId}.MechanicalMetrics",
"tenantId": "{tenantId}",
"name": "MechanicalMetrics",
"category": "dynamic",
"scope": "private",
"description": "Mechanical metrics for wind turbines",
"variables": [
{
"name": "V",
"unit": "RPM",
"searchable": true,
"qualityCode": true,
"defaultValue": null,
"dataType": "INT",
"length": null
},
{
"name": "VIB",
"unit": "Hz",
"searchable": true,
"qualityCode": true,
"defaultValue": null,
"dataType": "INT",
"length": null
}
],
"etag": {etagValue},
"_links": {
"self": {
"href": "{link}"
}
}
}
}
],
"fileAssignments": [],
"etag": {etagValue},
"_links": {
"self": {
"href": "{link}"
},
"parent": {
"href": "{link}"
}
},
"id": "{tenantId}.WT1000"
}
Modeling Assets¶
Creating Asset Sites¶
For reducing complexity, an asset of type basic.site
is created for each wind farm. This is done using the following endpoint:
POST /assets
For the wind farm in the North Sea, the body is:
{
"name": "North Sea",
"description": "Wind Farm North Sea",
"location": {
"longitude": 54.008333,
"latitude": 6.598333
},
"typeId": "core.basicarea",
"parentId": "{parentAssetId}",
"timezone": "Europe/Berlin"
}
The response of the call contains the newly created North Sea site asset so you can validate the correct creation:
{
"assetId": "{assetId}",
"tenantId": "{tenantId}",
"name": "North Sea",
"etag": {etagValue},
"externalId": null,
"t2Tenant": null,
"subTenant": null,
"description": "Wind Farm North Sea",
"timezone": "Europe/Berlin",
"parentId": "{parentAssetId}",
"typeId": "core.basicarea",
"location": {
"country": null,
"region": null,
"locality": null,
"streetAddress": null,
"postalCode": null,
"longitude": 54.008333,
"latitude": 6.598333
},
"fileAssignments": [],
"variables": [],
"aspects": [],
"locks": [],
"hierarchyPath": [
{
"assetId": "{assetId}",
"name": "{tenantId}"
}
],
"deleted": null,
"_links": {
"self": {
"href": "{link}"
},
"aspects": {
"href": "{link}"
},
"variables": {
"href": "{link}"
},
"location": {
"href": "{link}"
},
"parent": {
"href": "{link}"
}
}
}
The {parentAssetId}
is the root asset. Its ID can be requested using the following endpoint:
GET /assets/root
For the wind farm in the Baltic Sea, the body is:
{
"name": "Baltic Sea",
"description": "Wind Farm Baltic Sea",
"location": {
"longitude": 54.834,
"latitude": 14.068
},
"typeId": "core.basicarea",
"parentId": "{parentAssetId}",
"timezone": "Europe/Berlin"
}
The response of the call contains the newly created Baltic Sea site asset so you can validate the correct creation:
{
"assetId": "{assetId}",
"tenantId": "{tenantId}",
"name": "Baltic Sea",
"etag": 0,
"externalId": null,
"t2Tenant": null,
"subTenant": null,
"description": "Wind Farm Baltic Sea",
"timezone": "Europe/Berlin",
"parentId": "{parentAssetId}",
"typeId": "core.basicarea",
"location": {
"country": null,
"region": null,
"locality": null,
"streetAddress": null,
"postalCode": null,
"longitude": 54.834,
"latitude": 14.068
},
"fileAssignments": [],
"variables": [],
"aspects": [],
"locks": [],
"hierarchyPath": [
{
"assetId": "{parentAssetId}",
"name": "{tenantId}"
}
],
"deleted": null,
"_links": {
"self": {
"href": "{link}"
},
"aspects": {
"href": "{link}"
},
"variables": {
"href": "{link}"
},
"location": {
"href": "{link}"
},
"parent": {
"href": "{link}"
}
}
}
Creating Assets¶
After the asset sites are set up, the actual assets are created using the following endpoint:
POST /assets/
The body for the first asset for the wind farm of the North Sea is:
{
"name": "N-001",
"description": "Wind turbine 001 in North Sea",
"variables": [
{
"name": "InstallationDate",
"value": "2018-08-28T09:00:00+00:00"
}
],
"typeId": "{tenantId}.WT1000",
"parentId": "{AssetIdNorthSea}"
}
The {AssetIdNorthSea}
is the asset ID of the North Sea site asset.
The response of the call contains the newly created asset for the wind farm in the North Sea, so you can validate the correct creation:
{
"assetId": "{assetId}",
"tenantId": "{tenantId}",
"name": "N-001",
"etag": {etagValue},
"externalId": null,
"t2Tenant": null,
"subTenant": null,
"description": "Wind turbine 001 in North Sea",
"timezone": "Europe/Berlin",
"parentId": "{AssetIdNorthSea}",
"typeId": "{tenantId}.WT1000",
"location": {
"country": null,
"region": null,
"locality": null,
"streetAddress": null,
"postalCode": null,
"longitude": 54.008333,
"latitude": 6.598333
},
"fileAssignments": [],
"variables": [
{
"name": "InstallationDate",
"value": "2018-08-28T09:00:00+00:00"
}
],
"aspects": [],
"locks": [],
"hierarchyPath": [
{
"assetId": "{rootAssetId}",
"name": "{tenantId}"
},
{
"assetId": "{AssetIdNorthSea}",
"name": "North Sea"
}
],
"deleted": null,
"_links": {
"self": {
"href": "{link}"
},
"aspects": {
"href": "{link}"
},
"variables": {
"href": "{link}"
},
"location": {
"href": "{link}"
},
"parent": {
"href": "{link}"
}
}
}
The response shows that value of the type variable InstallationDate
of the asset is set to the value given in the request body. The default value defined by the asset type has been overwritten.
The asset has inherited its location from the North Sea site asset.
The asset has instantiated the aspects defined by its asset type WK1000
, but the aspect list is empty. This is because all its aspects are dynamic and aspect lists are only populated on asset level, if the aspect is defined as static.
The bodies for creating the other three assets are shown below:
{
"name": "N-002",
"description": "Wind turbine 002 in North Sea",
"variables": [
{
"name": "InstallationDate",
"value": "2018-08-28T09:00:00+00:00"
}
],
"typeId": "{tenantId}.WT1000",
"parentId": "{AssetIdNorthSea}"
}
{
"name": "B-001",
"description": "Wind turbine 001 in Baltic Sea",
"variables": [
{
"name": "InstallationDate",
"value": "2018-08-28T09:00:00+00:00"
}
],
"typeId": "{tenantId}.WT1000",
"parentId": "{AssetIdNorthSea}"
}
{
"name": "B-002",
"description": "Wind turbine 002 in Baltic Sea",
"variables": [
{
"name": "InstallationDate",
"value": "2018-08-28T09:00:00+00:00"
}
],
"typeId": "{tenantId}.WT1000",
"parentId": "{AssetIdNorthSea}"
}
Attention
The parentId
for the wind turbines in the Baltic Sea is intentionally set wrong for this example. The next section is based on this.
Moving assets¶
In the code given above the wind turbines B-001
and B-002
are inherited from the North Sea asset site instead of the Baltic Sea asset site. This can be corrected by moving both assets using the move endpoint:
POST /assets/{id}/move
The request requires the following parameters:
If-Match
: Has to be set as the{etagValue}
of the asset. The{etagValue}
is set to zero upon asset creation and incremented after each successful modification of the asset.id
: Has to be set as theassetId
of the asset. It is listed in the response when an asset is created.moveParameters
:{ "newParentId": "{AssetIdBalticSea}" }
The
{AssetIdBalticSea}
is the asset ID of the Baltic Sea site asset. After performing the move operation, the location ofB-001
andB-002
is correct.
Hint
If you forgot the individual asset IDs, you can get the list of all assets and their IDs by calling the following endpoint:
GET /assets
You can reduce the results using the filter
parameter:
{"name": "Baltic Sea"}