IBM Support

Logging data with Maximo and the BeagleBone Black using REST.

Technical Blog Post


Abstract

Logging data with Maximo and the BeagleBone Black using REST.

Body

A few weeks ago I entered a blog about getting data from Maximo using the REST API, Maximo, IoT and REST.

This blog will continue on with the REST example and show you one example on how to enter data into Maximo. For example, if you had a large tank and wanted to know the water level you could use a BeagleBone to read the water level and report it to Maximo. Imagine you have your BeagleBone Black setup to read a potentiometer that had an arm attached to a floating device in the tank. The potentiometer is now reading the angle of the arm and with this information you could calculate the water level. In my example however, I will just read the potentiometer and report a value between 0 and 1000 into Maximo.

First we need something in Maximo to report to, so let's add a Tank in the Asset application,

image

 

 

 

 

 

 

 

 

 

 

 

I then added a "WATERLEVEL" Meter to my Tank,

image

 

 

 

 

 

 

 

 

 

To register meter readings, I need to insert data into the MeasureMent object. This object is a little bit tricky to use since it requires an owner object. What this means is that I need to use an Object Structure to insert the data, I cannot use the Maximo Mbo object. In My case, I created the following "WATERLEVEL" Object Structure (OS),

image

 

The interesting part here is the path of the OS and how to refer to a specific Object in the OS via REST. I want to log data against my Tank Asset so that would be the root object, then the OS refer to the AssetMeter and then finally my Measurement object. To use children in an OS, Maximo uses a kind of "dot" notation, one example is found in the REST API documentation. So in my case I would refer to the Measurement with something like, assetmeter.id1.measurement.id2.measurementvalue=My_Value. The full URL to insert a NEW_VALUE reading would be something like, /maxrest/rest/os/waterlevelos/ASSET_ID?_lid=wilson&_lpwd=wilson&_compact=true&_format=json&assetmeter.id1.metername=WATERLEVEL&assetmeter.id1.linearassetmeterid=0&assetmeter.id1.measurement.id2.measurementvalue=NEW_VALUE&assetmeter.id1.measurement.id2.siteid=MY_SITE

There are two unknown here, the Unique ID and Site for the Tank, so I will use another REST call to get the data for our tank asset, /maxrest/rest/mbo/asset?_lid=wilson&_lpwd=wilson&_compact=true&_format=json&assetnum=TANK42.

This will return the the information about the Asset from Maximo and I can now build the full URL in my code to insert values into Maximo. In My example I will read the potentiometer in 5 seconds interval and insert the data into Maximo so it can be viewed in the Manage Meter Reading History.

image

 

So if you have a BeagleBone, enter the Asset, Meter and OS above and give it a try. Create a new Java Script in your Cloud9 environment.

image

 

Paste in the following code after updating the Application Server IP and Port Number,


// MaxRest02.js

// Use ordinary HTTP to communicate with Maximo
var http = require('http');
// Beagle Bone Script to be able to read potentiometer.
var bonescript = require('bonescript');

// Appserver IP and port.
var maximoAppServerIP = '192.168.0.242';
var maximoAppServerPort = '7001';

// Our Maximo Asset, Meter and Object Structure.
var AssetNum = 'TANK42';
var MeterName = 'WATERLEVEL';
var MeterOS = 'waterlevelos';

// Change if needed.
var userName = 'wilson';
var password = 'wilson';

// Interval to update Maximo in milliseconds, 5000 = 5 sec.
var interval = 5000;

// Variables, we need the unique ID and Site to insert the measurements.
var assetuid, siteid;

// Populate the variables and start data acquisition.
getAssetData();

// Get Asset data we need to add measurements.
function getAssetData() {

    // We are looking for asset MBOs, user password is wilson/wilson
    // Compact and format the response for Json
    // _urs=False to exclude row stamps.
    // assetnum=TANK42, look for our asset number.

    var GetURL = '/maxrest/rest/mbo/asset?_lid=' + userName + '&_lpwd=' + password + '&_compact=true&_format=json&assetnum=' + AssetNum;

    var assetURLOptions = {
        host: maximoAppServerIP,
        port: maximoAppServerPort,
        path: GetURL,
        method: 'GET'
        };

    // Uncomment for debug.
    //console.log('Get URL: ', GetURL);

    // Make a GET request...
    var getRequest = http.request(assetURLOptions, function(res) {

        // This is our response, the body.
        var body = '';

        // Fill up the body if more than one response.
        res.on('data', function(chunk) {
            body += chunk;
        });

        // We got a full response, parse it.
        res.on('end', function() {

            // Get JSON object.
            var asset = JSON.parse(body);

            // Print for debug, uncomment if you want to see the full response.
            //var prettyJson = JSON.stringify(asset, null, ' ');
            //console.log("Got response:\n", prettyJson);

            assetuid = asset.ASSETMboSet.ASSET[0].ASSETUID;
            siteid = asset.ASSETMboSet.ASSET[0].SITEID;

            // Now that we have the data, read the potentiometer at specified intervals.
            // The potentiometer is read and then the callback function logMeasurement is called.
            setInterval(function() {bonescript.analogRead('P9_40', logMeasurement)},interval);

        });

    });

    // Log any errors, hopefully none.
    getRequest.on('error', function(e) {
          console.log("Got error: ", e);
    });

    // End request.
    getRequest.end();

}

// Called in regular interval after the potentiometer is read.
function logMeasurement(reading) {

    // Get readings, scale by 1000 to make it more interesting.
    // The value can be between 0 and 1000 after the scaling.
    var value = reading.value * 1000;

    // We can now add measurements to Maximo by REST.
    // Use our new Object Structure to add measurement data.
    // Reference URL for "dot" notation
    // http://www-01.ibm.com/support/knowledgecenter/SSLKT6_7.5.0.5/com.ibm.mif.doc/gp_intfrmwk/rest_api/r_rest_post_method.html

    var PostURL = '/maxrest/rest/os/' + MeterOS + '/' + assetuid + '?_lid=' + userName + '&_lpwd=' + password + '&_compact=true&_format=json' +
        '&assetmeter.id1.metername=' + MeterName +
        '&assetmeter.id1.linearassetmeterid=0' +
        '&assetmeter.id1.measurement.id2.measurementvalue=' + value +
        '&assetmeter.id1.measurement.id2.siteid=' + siteid;

    var assetURLOptions = {
        host: maximoAppServerIP,
        port: maximoAppServerPort,
        path: PostURL,
        method: 'POST'
        };

    // Uncomment for debug.
    //console.log('Post URL: ', PostURL);

    console.log('Adding ', value, ' to the measurements.')

    // Make a POST request...
    var postRequest = http.request(assetURLOptions, function(res) {

        // This is our response, the body.
        var body = '';

        // Fill up the body if more than one response.
        res.on('data', function(chunk) {
            body += chunk;
        });

        // We got a full response, parse it.
        res.on('end', function() {

            // Print for debug, uncomment if you want to see the full response.
            //var asset = JSON.parse(body);
            //var prettyJson = JSON.stringify(asset, null, ' ');
            //console.log("Got response:\n", prettyJson);           

        });

    });

    // Log any errors, hopefully none.
    postRequest.on('error', function(e) {
          console.log("Got error: ", e);
    });

    // End request.
    postRequest.end();
}


Add a potentiometer to your BeagleBone and have fun,

image

 

[{"Business Unit":{"code":"BU059","label":"IBM Software w\/o TPS"},"Product":{"code":"SSLKT6","label":"IBM Maximo Asset Management"},"Component":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"","Edition":"","Line of Business":{"code":"LOB59","label":"Sustainability Software"}}]

UID

ibm11131909