The Information Model Service supports the modeling of various entities varying from simple to incredibly complex. It is desirable to present the entity as detailed as needed. However, such a model can still be too detailed for certain purposes, so extracting part of the object for multiple information models might be necessary to focus on a limited set of properties, variables, etc.

For example, we can take properties related to the cost associated with the actual device. In this case, there is no need to pass around a large object with information that is immediately discarded. It is better to provide information that is needed and useful.

This case would benefit from using related models by exposing different views of the same object to represent each aspect of the large object.

An object model can have 0, 1, or many related object models, each one presenting a different aspect of the same entity. A good analogy is an orthographic projection, and here is an example of angle projection:

First_angle_projection
Emok, First angle projection, CC BY-SA 3.0

Object is shown with three different views (projections). Each of them provides different information about the object and focuses on a different perspective.

In the information modeling context, each related model is our projection over an actual object. Each related model provides a piece of information about the same object but from a different perspective.

# Information Model

Information Model Service may be used for creating objects that are related. The "main" type definition may contain relatedModels property to point related models explicitly to use that feature. This ensures that objects of each related model will be automatically created.

Removing related models

Information Model Service does not automatically remove related models - this has to be done manually for each of them individually.

The same effect might be achieved by creating objects with the same objectId, but it is the user's responsibility to ensure the correct handling of the object's lifecycle.

# Model definition vs Type definition

Ability Platform by default provides abb.ability.device and abb.ability.configuration model definitions. Those might be used to create type definitions that create a logical connection between the configuration and the device. This approach is common for Edge devices, i.e. when those two models represent a single device to represent two aspects of it.

The model definition itself does not define relations, and this is done on the type definition level. This is an example of a type, which defines relation.

{
    "model": "abb.ability.device",
    "typeId": "robot.scara",
    "version": "1.0.0",

    "relatedModels": {
        "abb.ability.configuration": {
            "type": "robot.scara.configuration@1"
        },
        "robots.joints": {
            "type": "robot.scara.joints@1"
        }
    }
}

In this example, the object that represents the SCARA robot might be described by three models:

  • abb.ability.device - main model that defines basic properties
  • abb.ability.configuration - configuration of the robot
  • robots.joints - information about joints.

# Object instance

Another important aspect is how related models are instantiated while object of the 'main' type is created ('main type' means here a type definition that has relatedModels component).

Information Model assures correctness of the created object, so if the type has relatedModels, an instance of each related model (defined with type) will be created. To express connection between those instances, all of them use the same objectId property, and can be recognized by the type.

# When to use it?

The feature is ideal for large and complex objects. With related models, we can break down the structure of such objects logically and expose a certain aspect of it. An advantage of this approach is the ability to present various perspectives, i.e.:

  • structure of a complicated device
  • information related to maintenance (time between failures, cost of used raw materials)

From a security standpoint, involved services know just enough about the source object as access to specific models can be limited using grants with rules.

# Example

# Overview

Let's create the Information Model object, that represents SCARA robot.

The main type is robot.scara - it uses the default model abb.ability.device. This type defines two related models: robot.scara.configuration and robots.joints - we need types of those models also. When all models and types are present, we can create the object.

Whole example might be done with the Playground.

# Create models, types and object

  1. Create custom model robots.joints (POST /modelDefinitions):
{
  "modelId": "abb.robots.joints",
  "name": "model definition for joints of SCARA robot",
  "description": "model definition for joints of SCARA robot",
  "tags": [
    "Robotics"
  ],
  "components": {
    "properties": {
      "controllerId": {
        "dataType": "string"
      }
    },
    "variables": {},
    "methods": {},
    "events": {},
    "alarms": {},
    "references": {},
    "attributes": {}
  }
}
  1. Create Type robot.scara.configuration. It uses default model abbb.ability.configuration (POST /modelDefinitions/{modelId}/types):
{
  "model": "abb.ability.configuration",
  "typeId": "robot.scara.configuration",
  "version": "1.0.0",

  "properties": {
    "serialNumber": {
      "dataType": "string",
      "isMandatory": true
    },
    "controllerFamily": {
      "dataType": "string",
      "isMandatory": true
    }
  }
}
  1. Create type abb.robot.scara.joints built on custom model (POST /modelDefinitions/{modelId}/types):
{
  "model": "abb.robots.joints",
  "typeId": "abb.robot.scara.joints",
  "version": "1.0.0",
  "properties": {
    "controllerId": {
      "dataType": "string"
    }
  },
  "variables": {
    "torque": {
      "dataType": "map",
      "values": "number"
    },
    "velocity": {
      "dataType": "map",
      "values": "number"
    }
  }
}
  1. Create type definition abb.robot.scara. This type uses default model abb.ability.device (POST /modelDefinitions/{modelId}/types). This type contains property relatedModels that defines related models created automatically by Information Model Service while this type will be instantiated.
{
  "model": "abb.ability.device",
  "typeId": "abb.robot.scara",
  "version": "1.0.0",

  "properties": {
    "controllerId": {
      "dataType": "string"
    },
    "serialNumber": {
      "dataType": "string",
      "isMandatory": true
    },
    "controllerFamily": {
      "dataType": "string",
      "isMandatory": true
    }
  },
  "variables": {
    "torque": {
      "dataType": "map",
      "values": "number"
    },
    "velocity": {
      "dataType": "map",
      "values": "number"
    }
  },
  "relatedModels": {
    "abb.ability.configuration": {
        "type": "robot.scara.configuration@1"
    },
    "abb.robots.joints": {
        "type": "abb.robot.scara.joints@2"
    }
  }
}
  1. Create Information Model object for the abb.ability.device aspect of our entity (POST /objects):
{
  "model": "abb.ability.device",
  "type": "abb.robot.scara",
  "name": "SCARA robot",
  "properties": {
    "controllerId": {
      "value": "ABB-123"
    },
    "serialNumber": {
      "value": "123456"
      },
    "controllerFamily": {
      "value": "ABB-SCARA-Controller"
      }
    },
    "variables": {
    "torque": {
      "value":  {
        "joint1": {
            "value": 0
        },
        "joint2": {
            "value": 0
        },
        "joint3": {
            "value": 0
        },
        "joint4": {
            "value": 0
        }
      }
    },
    "velocity": {
      "value":  {
        "joint1": {
            "value": 0
        },
        "joint2": {
            "value": 0
        },
        "joint3": {
            "value": 0
        },
        "joint4": {
            "value": 0
        }
      }
    }
  }
}
  1. InfoModel Schema Metadata Management: Workflow information like Latest Status, Last updated Timestamp can be added to the output response of model definition with help of workflow collection stored in database. Fetch this information via Getworkflow end point in the API as:

Infomodel Delete Endpoint

The output of new Getworkflow API for model definition will be like below :

{
      "modelId": "abb.ability.configuration",
      "group": "config models",
      "components": {
        "properties": {},
        "attributes": {}
      },
      "version": 1,
      "isDeleted": false,
      "WorkFlowStatus": {
        "CreateTimeStamp": "2024-05-15T07:18:42Z",
        "LastUpdateTimeStamp": "2024-06-20T09:05:59Z",
        "ModeOfCreation": "TextSchema",
        "TypeSchemaUsage": 4968
      }
    }

As you can see in the response below, Information Model Service has created three objects for us with one request:

{
  "objectId": "4cf06b56-3f5a-4574-a0bb-205e64ddf8af",
  "model": "abb.ability.device",
  "relatedModels": [
    {
      "objectId": "4cf06b56-3f5a-4574-a0bb-205e64ddf8af",
      "model": "abb.ability.configuration"
    },
    {
      "objectId": "4cf06b56-3f5a-4574-a0bb-205e64ddf8af",
      "model": "abb.robots.joints"
    }
  ]
}

# Summary

We may not know what models use our object, but IM service can provide such information for us (GET /objects/{objectId}/models):

{
  "data": [
    "abb.ability.device",
    "abb.robots.joints",
    "abb.ability.configuration"
  ]
}

Let's take a look at our object from the perspective of each model (GET /objects/{objectId}/models/{modelId}):

  1. Object from abb.ability.device perspective:
{
  "model": "abb.ability.device",
  "properties": {
    "controllerId": {
      "dataType": "string",
      "value": "ABB-123"
    },
    "serialNumber": {
      "dataType": "string",
      "isMandatory": true,
      "value": "123456"
    },
    "controllerFamily": {
      "dataType": "string",
      "isMandatory": true,
      "value": "ABB-SCARA-Controller"
    }
  },
  "variables": {
    "torque": {},
    "velocity": {}
  },
  "relatedModels": {
    "abb.ability.configuration": {
      "type": "robot.scara.configuration@1"
    },
    "abb.robots.joints": {
      "type": "abb.robot.scara.joints@2"
    }
  },
  "isDeleted": false,
  "type": "abb.robot.scara@2",
  "name": "SCARA robot",
  "version": 1,
  "lastModified": "2021-12-03T13:23:13.838Z",
  "objectId": "4cf06b56-3f5a-4574-a0bb-205e64ddf8af",
  "tenantId": "f4831d89-9f60-471a-b063-5fbcda46584b"
}
  1. The same object from abb.ability.configuration perspective:
{
  "model": "abb.ability.configuration",
  "properties": {
    "serialNumber": {
      "dataType": "string",
      "isMandatory": true
    },
    "controllerFamily": {
      "dataType": "string",
      "isMandatory": true
    }
  },
  "isDeleted": false,
  "type": "robot.scara.configuration@1",
  "version": 1,
  "lastModified": "2021-12-03T13:23:13.958Z",
  "objectId": "4cf06b56-3f5a-4574-a0bb-205e64ddf8af",
  "tenantId": "f4831d89-9f60-471a-b063-5fbcda46584b"
}
  1. The same object from robots.joints perspective:
{
  "model": "abb.robots.joints",
  "properties": {
    "controllerId": {
      "dataType": "string"
    }
  },
  "variables": {
    "torque": {},
    "velocity": {}
  },
  "isDeleted": false,
  "type": "abb.robot.scara.joints@2",
  "version": 1,
  "lastModified": "2021-12-03T13:23:13.92Z",
  "objectId": "4cf06b56-3f5a-4574-a0bb-205e64ddf8af",
  "tenantId": "f4831d89-9f60-471a-b063-5fbcda46584b"
}
Last updated: 7/26/2024, 7:00:24 AM
Feedback