LIBPF® RESTful Model User API manual

Introduction

Intended audience

System integrators and app developers who wish to develop solutions based on the modeling of industrial continuous processes with the LIBPF® enabling technology, in particular solutions where a service or a web app or a mobile app interacts with the process models exposed as a web service.

Scope

This document is the interface manual for the HTTP RESTful incarnation of the LIBPF® Model User API, a simple, high-level API to manage and use process models who have been previously prepared and deployed by model developers.

The idea of the RESTful Model User API is to make a subset of the Model User functionalities accessible as a synchronous RESTful web service, complying with the REST (REpresentational State Transfer) architectural constraints.

Prerequisites

The RESTful Model User API

Concepts

Each service running the Model User RESTful API essentially matches the capabilities of a standalone kernel, i.e. knows how to instantiate and manipulate a set of types, which share the same list of components.

Each service will be made available at the service base URL within a hierarchical URL structure, for example:

https://simevo.com/api/process/pasteurize
https://simevo.com/api/process/biogas
https://simevo.com/api/process/pyrolization
https://example.com/api
...

The services may evolve in time (they are versioned) and a specific service + service version is identified by a unique service uuid (Universally unique identifier). But service uuids are not exposed in the URL, because we do not want all URLs contained in a service to become invalid when a service is upgraded. The service always returns a service_uuid field in each response, and it is the client responsibility to check that the returned value of the service_uuid field matches the service uuid of the service the client thinks it is connecting to.

The services URL cannot be “changed” using the HTTP POST and DELETE verbs, but only accessed with the read-only HTTP GET verb to query the service information, supported types and enumerators and theme-related files (icon, background and assets), as detailed in the Service management chapter below.

Inside a service there is the cases collection located at the cases URL, for example:

https://simevo.com/api/process/pasteurize/cases

Each case is identified by a unique case_uuid which is a representation of an instance of the LIBPF® Model User API Handle object.

The case_uuid is exposed in the URL to create a persistent case URL:

https://simevo.com/api/process/pasteurize/cases/b14d48e0-1285-11e4-9191-0800200c9a66

The case URL can be made persistent even after a service upgrade, provided the necessary case migration procedure is performed on the service back-end.

The cases URL can be “changed” using the POST and DELETE HTTP verbs, to create new cases, apply changes to a case and calculate it, delete a case, clone a case or purge all cases. Accessing a specific case URL with the read-only HTTP GET verb allows to query the case information, get the case as sqlite database, SQL dump of the sqlite database, text or HTML, the case graphical assets, and the value of a specific quantity, as detailed in the Case management chapter below.

Status codes and error handling

The RESTful Model User API uses HTTP status codes as the primary mechanism to report success or error.

All endpoints in case of success return 200 as HTTP status code, except for POST requests that return 201.

The HTTP status codes in case of errors are:

Furthermore when applicable in case of error the response body contains a JSON document similar to:

{ 
    "service_uuid": "62e3a255-c1a0-4dea-a650-05b9a4a33aef",
    "error": error,
    "message": message
}

where:

Implementation

The Model User RESTful API is implemented using bottle, a simple and lightweight WSGI micro web-framework for Python.

The entire web service implementation is a ~ 600 SLOC Python piece of code, available with an Open Source GPL3 license.

If you wish to set up your own services you should:

  1. develop the models of the industrial continuous processes of interest using the C++ LIBPF® CORE SDK (this is the task of model developers)

  2. wrap your models with a Python Model User API, using SWIG and the LIBPF® PYTHON SDK - see the LIBPF® Python Model User API manual

  3. set up a service in the public or private cloud, using the GPLv3-licensed web service

  4. if your new service is meant to be public, publish it with the service list discovery URL (see “API Endpoints - Service discovery” below)

URLs

In the following the API is presented from the root of the service address space as in:

GET /cases/b14d48e0-1285-11e4-9191-0800200c9a66/quantities/S01.T

In the real world the complete version of these same URLs will probably look like this for a public server (which is the form in which in the following test URLs are provided):

https://simevo.com/api/process/pasteurize/cases/b14d48e0-1285-11e4-9191-0800200c9a66/quantities/S01.T

or:

http://192.168.0.1:8080/cases/b14d48e0-1285-11e4-9191-0800200c9a66/quantities/S01.T

for a private server.

API Endpoints

Service discovery

Service discovery for publicly available services is performed by contacting with the HTTP GET verb the service list URL, hard-coded as:

GET https://simevo.com/api/process.json

Parameters: none

It is guaranteed to return a JSON document similar to:

{
  "services" : [{
    "service_uuid" : "62e3a255-c1a0-4dea-a650-05b9a4a33aef",
    "url" : "https://simevo.com/api/process/pasteurize/",
    "status" : "alive"
  }, {
    "service_uuid" : "e912989f-9b8f-4d4a-9bd6-f0c351fd770a",
    "url" : "https://simevo.com/api/process/geometry/",
    "status" : "dead",
    "message": "scheduled maintenance, the service will resume at 20:00 CET 2015/0/01"
  }, {
    "service_uuid" : "1187ffe2-497c-4a5e-b03a-b5f479499c9d",
    "url" : "https://simevo.com/api/process/gasify/",
    "status" : "deactivated"
  }, {
    "service_uuid" : "f8d83420-08e1-11e4-9191-0800200c9a66",
    "url" : "https://simevo.com/api/process/biogas/",
    "status" : "migrated",
    "new_service_uuid" : "c955d830-2e82-11e4-8c21-0800200c9a66"
  }]
}

The JSON Schema for the returned JSON is the discovery_schema.json.

For each of these services detailed discovery is performed by contacting the service url (see “Service management / query service info” below).

Test with:

curl -k -i -X GET https://simevo.com/api/process.json

Service management

Query service info

GET /

Parameters: none

Sample data:

{
  "description": "Process modeling of continuous pasteurization processes",
  "color": "#228B22",
  "service_uuid": "62e3a255-c1a0-4dea-a650-05b9a4a33aef",
  "uptime": 16000757.0,
  "name": "Pasteurize",
  "license": "(C) Copyright 2014-2015 Paolo Greppi simevo s.r.l.",
  "url": "https://simevo.com/api/process/pasteurize/",
  "info_url": "https://libpf.com/demos/pasteurization/",
  "stamp": 1456394094.0,
  "version": "00.03.01 [2015/04/10 07:00:00]",
  "calls": 256,
  "api_version": "0.1"
}

Individual fields notes:

The JSON Schema for the returned JSON is kernel_schema.json.

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/

Query supported types

GET /types

Parameters: none

In case of success returns a JSON document similar to:

{
  "service_uuid": "62e3a255-c1a0-4dea-a650-05b9a4a33aef",
  "types": [
    {
      "name": "chiller",
      "description": "packaged chiller unit",
      "category": "flowsheet",
      "instantiable": true,
      "integerOptions": [
        {
          "name": "stages",
          "value": 2,
          "min": 1,
          "max": 10
        }
      ],
      "stringOptions": [
        {
          "name": "type",
          "value": "scroll",
          "enumerator": "compressorType"
        }
      ]
    }
  ]
}

where the “service_uuid” field echoes the current service uuid and the “types” field contains a UTF-8 encoded, JSON-serialized vector of [TypeDescriptor objects] .

The JSON Schema for the returned JSON is types_schema.json.

The types[i]/name can be passed to the POST /cases API in the type field of the casedescriptor parameter, but only if types[i]/instantiable is true.

The types[i]/integerOptions[j]/name can be passed as key of a integerOptions field of the casedescriptor, where the corresponding value is in the [types[i]/integerOptions[j]/min .. types[i]/integerOptions[j]/max_] range (inclusive). The types[i]/stringOptions[j]/name can be passed as key of a stringOptions field of the casedescriptor, where the corresponding value is one of the values of the corresponding types[i]/stringOptions[j]/enumerator.

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/types

Query supported enumerators

GET /enumerators

Parameters: none

In case of success returns a JSON document similar to:

{
  "service_uuid": "62e3a255-c1a0-4dea-a650-05b9a4a33aef",
  "enumerators": [
    {
      "name": "processType",
      "description": "Process type - sets predefined temperature and holding time for the process",
      "options": [
        {
          "name": "HTST25",
          "description": "High Temperature Short Time - highT = 353.15 K holdTime = 25.0 s"
        },
        {
          "name": "HTST15",
          "description": "High Temperature Short Time - highT = 356.15 K holdTime = 15.0 s"
        },
        {
          "name": "HHST3",
          "description": "Higher Heat Shorter Time - highT = 363.15 K holdTime = 3.0 s"
        },
        {
          "name": "HHST1",
          "description": "Higher Heat Shorter Time - highT = 363.15 K holdTime = 1.0 s"
        },
        {
          "name": "user",
          "description": "user specified - initial values highT = 363.15 K holdTime=1.0 s, user adjustable",
          "default": true          
        }
      ]
    }
  ]
}

where the “service_uuid” field echoes the current service uuid and the “enumerators” field contains a UTF-8 encoded, JSON-serialized vector of SmartEnumerator-derived types.

The JSON Schema for the returned JSON is enumerators_schema.json.

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/enumerators

Get service icon

GET /icon

Parameters: none

Returns a vector graphic in SVG format with an icon that clients can use to represent graphically the service.

The style guide for the service icon is:

Sample service icon:

alt Service icon

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/icon

Get service theme background

GET /background/<maxsize>

Parameters:

Returns a raster graphic in JPG format with a background that clients can use to theme graphically the service.

The service will resize the image so that the maximum size (horizontal or vertical) is maxsize.

The style guide for the service theme background is:

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/background/200

Get service graphical assets

GET /assets

Parameters: none

Returns the service graphical assets in the form of a list of URLs to graphical assets (typically SVG files).

Clients must individually access those URLs to download the assets.

Sample output:

{
  "service_uuid": "62e3a255-c1a0-4dea-a650-05b9a4a33aef",
  "assets": [
    "https://simevo.com/api/process/pasteurize/assets/Arrow.svg",
    "https://simevo.com/api/process/pasteurize/assets/PasteurHTST15_milkWhole.svg"
  ]
}

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/assets
curl -k -i -X GET https://simevo.com/api/process/pasteurize/assets/Arrow.svg
curl -k -i -X GET https://simevo.com/api/process/pasteurize/assets/PasteurHTST15_milkWhole.svg

Case management

Create a new case

POST /cases

Parameters: the request body should contain a UTF-8 encoded, JSON-serialized CaseDescriptor object; if the request body is empty, the default will result in a case of type defaultType to be created with empty tag and description.

See the CaseDescriptor class reference.

The JSON Schema for the request body JSON is caseDescriptor.json.

In case of success returns a JSON document similar to:

{
  "service_uuid": "e688e78c-c36f-48be-ab96-35fadfdc251a",
  "url": "https://simevo.com/api/process/pasteurize/cases/3b47dca0-1bda-4bea-8334-cc42393f1940"
  "case_uuid": "3b47dca0-1bda-4bea-8334-cc42393f1940",
  "type": "aaaaaaaaaa",
  "tag": "bbbbbbbbbbbbbb",
  "description": "cccccccccccccccccccccc",
  "created_at": 1406301601,
  "modified_at": 1406301601
}

where:

Test with:

curl -k -i -X POST -H "Content-Type: application/json" -d '{"type": "aaa", "tag": "bbbbbbb"}' https://simevo.com/api/process/pasteurize/cases

Query case info

GET /cases/&lt;case_uuid&gt;

Parameters:

In case of success returns a JSON document similar to:

{
  "service_uuid": "e688e78c-c36f-48be-ab96-35fadfdc251a",
  "url": "https://simevo.com/api/process/pasteurize/cases/3b47dca0-1bda-4bea-8334-cc42393f1940"
  "case_uuid": "3b47dca0-1bda-4bea-8334-cc42393f1940",
  "type": "aaaaaaaaaa",
  "tag": "bbbbbbbbbbbbbb",
  "description": "cccccccccccccccccccccc",
  "created_at": 1406301601,
  "modified_at": 1406301601
}

where:

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/3b47dca0-1bda-4bea-8334-cc42393f1940

Apply changes to a case and calculate it

Calculate the case identified by the specified case_uuid

POST /cases/&lt;case_uuid&gt;

Parameters:

In case of success returns a JSON document similar to:

{
  "service_uuid": "e688e78c-c36f-48be-ab96-35fadfdc251a",
  "url": "https://simevo.com/api/process/pasteurize/cases/3b47dca0-1bda-4bea-8334-cc42393f1940"
  "case_uuid": "3b47dca0-1bda-4bea-8334-cc42393f1940",
  "type": "aaaaaaaaaa",
  "tag": "bbbbbbbbbbbbbb",
  "description": "cccccccccccccccccccccc",
  "created_at": 1406301601,
  "modified_at": 1406301601
}

where:

Test with:

curl -k -i -X POST https://simevo.com/api/process/pasteurize/cases/3b47dca0-1bda-4bea-8334-cc42393f1940/calculate
curl -k -i -X POST -d '{ "controlled": [{ "variable": "feed", "end": 3000.0 }, { "variable": "coolT", "end": 300.0 } ] }' https://simevo.com/api/process/pasteurize/cases/3b47dca0-1bda-4bea-8334-cc42393f1940/calculate

Delete a case

Deletes the case identified by the specified case_uuid

DELETE /cases/&lt;case_uuid&gt;

Parameters:

In case of success returns a JSON document similar to:

{
  "service_uuid": "62e3a255-c1a0-4dea-a650-05b9a4a33aef"
}

where the “service_uuid” field echoes the current service uuid.

Test with:

curl -k -i -X DELETE https://simevo.com/api/process/pasteurize/cases/b14d48e0-1285-11e4-9191-0800200c9a66

Get case as sqlite database

Retrieves the case identified by the specified case_uuid as a sqlite database file.

GET /cases/&lt;case_uuid&gt;/db

Parameters:

In case of success returns the sqlite database.

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/b14d48e0-1285-11e4-9191-0800200c9a66/db

Get case as SQL dump of the sqlite database

Retrieves the case identified by the specified case_uuid as the SQL dump of the sqlite database.

GET /cases/&lt;case_uuid&gt;/sql

Parameters:

In case of success returns the SQL dump of the sqlite database as a text file, which can be fed to sqlite3 CLI to re-create the database:

cat dump.sqlite | sqlite3 persistency.db 

Sample output:

BEGIN TRANSACTION
...
CREATE TABLE N (
        ID                      integer PRIMARY KEY,
        TAG                     character (50),
        DESCRIPTION             character (255),
        TYPE                    character (50),
        FULLTAG                 character (255),
        UUID                    character (36),
        CREATED_AT              datetime,
        UPDATED_AT              datetime,
        LOCKED_BY               character (50),
        LOCKED_UNTIL            datetime,
        PARENT                  integer REFERENCES N (ID),
        ROOT                    integer REFERENCES N (ID),
        RANGE                   integer
);
INSERT INTO "N" VALUES(0,'','','C1000','','704653b0-b668-4e1d-98db-8275c5e5909e',NULL,NULL,NULL,NULL,0,0,129);
INSERT INTO "N" VALUES(1,'source','Source of all feed streams to the graph','Terminator',':source','7b0d2fb1-a777-45a0-b909-d30ee825e15a',NULL,NULL,NULL,NULL,0,0,1);
INSERT INTO "N" VALUES(2,'sink','Destination for all streams exiting the graph','Terminator',':sink','21d6e120-7686-4d31-8eef-8ca3f4b31564',NULL,NULL,NULL,NULL,0,0,1);
INSERT INTO "N" VALUES(3,'A','First unit','MicroTurbine',':A','3e945c37-4416-4897-a9e0-78bbd9924bc3',NULL,NULL,NULL,NULL,0,0,26);
...
CREATE TABLE Q (
        ID                      integer PRIMARY KEY,
        NID                     integer REFERENCES N (ID),
        TAG                     character (50),
        DESCRIPTION             character (255),
        VALUE                   double precision,
        UNIT                    character (50),
        INPUT                   boolean,
        OUTPUT                  boolean
);
INSERT INTO "Q" VALUES(1,0,'LHV_CH4','methane Lower Heating Value',802618000.0,'kmol^-1 m^2 kg s^-2',0,0);
INSERT INTO "Q" VALUES(2,0,'LHV_CO','carbon monoxide Lower Heating Value',282980000.0,'kmol^-1 m^2 kg s^-2',0,0);
INSERT INTO "Q" VALUES(3,0,'LHV_H2','hydrogen Lower Heating Value',241814000.0,'kmol^-1 m^2 kg s^-2',0,0);
INSERT INTO "Q" VALUES(4,0,'cduty','Cumulative enthalpy flow inlet minus outlet',1.0,'m^2 kg s^-3',0,1);
INSERT INTO "Q" VALUES(5,0,'cmdot','Cumulative mass flow inlet minus outlet',1.0,'kg s^-1',0,1);
...
COMMIT;

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/b14d48e0-1285-11e4-9191-0800200c9a66/sql

Get case as text

Retrieves the case identified by the specified case_uuid as a text file.

GET /cases/&lt;case_uuid&gt;/txt

Parameters:

In case of success returns the text file dump.

Sample output:

****** type = C1000 TAG =  << DESCRIPTION 
*** Begin String attributes
constraints =  Used to persist connectivity constraints
*** Begin StringVector attributes
errors = [] Errors from the last computation
warnings = [convergence on deltax; dubious convergence, source stream S01 is not connected to any external inlet stream nor is it a cut stream @ A, Zero flow of key component CO @ A:RX:reactions[1], Zero flow of key component H2 @ A:RX:reactions[2], source stream S01 is not connected to any external inlet stream nor is it a cut stream @ B, Zero flow of key component CO @ B:RX:reactions[1], Zero flow of key component H2 @ B:RX:reactions[2], source stream S01 is not connected to any external inlet stream nor is it a cut stream @ C, Zero flow of key component CO @ C:RX:reactions[1], Zero flow of key component H2 @ C:RX:reactions[2], source stream S01 is not connected to any external inlet stream nor is it a cut stream @ D, Zero flow of key component CO @ D:RX:reactions[1], Zero flow of key component H2 @ D:RX:reactions[2], ] Warnings from the last computation
*** Begin Quantity attributes
LHV_CH4 = 802618000 kmol^-1 m^2 kg s^-2 methane Lower Heating Value
LHV_CO = 282980000 kmol^-1 m^2 kg s^-2 carbon monoxide Lower Heating Value
LHV_H2 = 241814000 kmol^-1 m^2 kg s^-2 hydrogen Lower Heating Value
cduty = 1 m^2 kg s^-3 Cumulative enthalpy flow inlet minus outlet
cmdot = 1 kg s^-1 Cumulative mass flow inlet minus outlet
...
*** End source Source of all feed streams to the graph

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/b14d48e0-1285-11e4-9191-0800200c9a66/txt

Get case as HTML

Retrieves the case identified by the specified case_uuid in HTML format.

GET /cases/&lt;case_uuid&gt;/html

Parameters:

In case of success returns a summary for the case in HTML format.

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/b14d48e0-1285-11e4-9191-0800200c9a66/html

Get case graphical assets

GET /cases/&lt;case_uuid&gt;/assets

Parameters:

Returns the case graphical assets in the form of a list of URLs to graphical assets (typically SVG files).

Clients must individually access those URLs to download the assets.

Sample output:

{
  "service_uuid": "e688e78c-c36f-48be-ab96-35fadfdc251a",
  "assets": [
    "https://simevo.com/api/process/pasteurize/cases/a258d84e-b01d-4bb1-8789-9d27566e7a21/assets/0.svg",
    "https://simevo.com/api/process/pasteurize/cases/a258d84e-b01d-4bb1-8789-9d27566e7a21/assets/3.svg",
    "https://simevo.com/api/process/pasteurize/cases/a258d84e-b01d-4bb1-8789-9d27566e7a21/assets/7.svg",
    ...
    "https://simevo.com/api/process/pasteurize/cases/a258d84e-b01d-4bb1-8789-9d27566e7a21/assets/1.svg"
  ]
}

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/a258d84e-b01d-4bb1-8789-9d27566e7a21/assets
curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/a258d84e-b01d-4bb1-8789-9d27566e7a21/assets/0.svg
curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/a258d84e-b01d-4bb1-8789-9d27566e7a21/assets/3.svg

Get a specific quantity

Retrieve the quantity with specified path in the case identified by the specified case_uuid

GET /cases/&lt;case_uuid&gt;/quantities/<path>

Parameters:

In case of success returns a JSON document similar to:

{
  "service_uuid" : "62e3a255-c1a0-4dea-a650-05b9a4a33aef",
  "case_uuid": "3b47dca0-1bda-4bea-8334-cc42393f1940",
  "path": "HOLD.V",
  "value": 0.00103581319956551
}

where:

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/3b47dca0-1bda-4bea-8334-cc42393f1940/quantities/HOLD.V

Clone a case

Clones the case identified by the supplied case_uuid

GET /cases/&lt;case_uuid&gt;/clone

Parameters:

In case of success returns a JSON document similar to:

{
  "service_uuid": "e688e78c-c36f-48be-ab96-35fadfdc251a",
  "url": "https://simevo.com/api/process/pasteurize/cases/3b47dca0-1bda-4bea-8334-cc42393f1940"
  "case_uuid": "3b47dca0-1bda-4bea-8334-cc42393f1940",
  "type": "aaaaaaaaaa",
  "tag": "bbbbbbbbbbbbbb",
  "description": "cccccccccccccccccccccc",
  "created_at": 1406301601,
  "modified_at": 1406301601
}

where:

Test with:

curl -k -i -X GET https://simevo.com/api/process/pasteurize/cases/b14d48e0-1285-11e4-9191-0800200c9a66/clone

Purge all cases

Deletes all existing case instances

DELETE /cases

Parameters: none

In case of success returns a JSON document similar to:

    { "service_uuid": "62e3a255-c1a0-4dea-a650-05b9a4a33aef" }

where the “service_uuid” field echoes the current service uuid.

Test with:

curl -k -i -X DELETE https://simevo.com/api/process/pasteurize/cases

Reference

Tools