Skip to content

Maximo JSON API: An IoT Example

I’ve had a lot of conversations recently with folks attempting to implement more Condition Monitoring within their organization. The benefits of shifting from time-based maintenance to condition- or use-based maintenance are well documented and very real. However, making that shift involves a fair amount of planning, analysis, and technology. This article will show an example of how to bridge a small portion of the technology gap; specifically we will focus on creating meter readings in Maximo via the JSON API available in Maximo 7.6.0.2 and higher. Meter readings are the heart of how Condition Monitoring is implemented in Maximo. They represent a piece of data at a point in time associated with an asset. This data could be related to the asset’s condition such as temperature, pressure, voltage, etc. This data could also be related to the asset’s usage such as an odometer reading, the number of cycles of the asset, etc. Lastly, the data could be based on a simple value list such as Pass/Fail, Open/Closed, Blowing / Not Blowing, etc. To create a new meter reading via Maximo’s JSON API, let’s start with an example:
POST http://mxapprove.a3jgroup.com/maximo/oslc/os/mxasset/_QkVERk9SRC8xMTQ1MA==?lean=1
maxauth: c21pdGg6c21pdGgx
Content-Type: application/json
properties: *
x-method-override: PATCH
patchtype: MERGE
{
    "assetmeter": [
        {
            "metername": "O-PRESSUR",
            "linearassetmeterid": 0,
            "newreading": "4900"
        }
    ]
}
Let’s look at this part-by-part. First, we start with the HTTP POST itself.
POST /maximo/oslc/os/mxasset/_QkVERk9SRC8xMTQ1MA==?lean=1
This message needs to be an HTTP POST (not HTTP GET). The http://mxapprove.a3jgroup.com/maximo portion of the URL is your Maximo environment’s URL. Substitute that for your own environment’s URL. The /oslc part of the path represents the usage Maximo JSON API. The /os part of the path tells the API that the next part of the path (in our example is /mxasset) will be an Object Structure in Maximo. Finally, the /_QkVERk9SRC8xMTQ1MA== represents a unique identifier for an Asset record that can be referenced in the MXASSET Object Structure. This identifier can be found be querying for the asset using an HTTP GET to the same MXASSET Object Structure, or it can be derived by base64 encoding the asset’s SITEID + “/” + ASSETNUM and prefixing that string with an underscore (“_”) character. The ?lean=1 part of the path allows us to not have to specify namespace prefixes in the body of the request. Next are the various headers.
maxauth: c21pdGg6c21pdGgx
Content-Type: application/json
properties: *
x-method-override: PATCH
patchtype: MERGE
The maxauth header represents the credentials that are being used to broker the transaction. The value is a base64 encoded string of the format USERNAME + “:” PASSWORD. In an LDAP environment, switch the maxauth header to Authorization and prefix the string “Basic ” to the base64 encoded value. The Content-Type header tells the HTTP request that the body of the message will be in JSON format. The properties header tells the request which fields from the MXASSET Object Structure should be sent back in the HTTP response, with the * character representing all fields in the object structure. The x-method-override header with a value of PATCH tells Maximo that this will be an update to the asset record, and the patchtype header with a value of MERGE tells Maximo to add a new record while keeping the other ASSETMETER records. Without that header, the integration will replace all of the ASSETMETER records with the list in the message. Next is the body of the message.
{
    "assetmeter": [
        {
            "metername": "O-PRESSUR",
            "linearassetmeterid": 0,
            "newreading": "4900"
        }
    ]
}
Note that we don’t need any identifying information about the asset in the message body, such as the ASSETNUM or SITEID. This is because we are required to specify the unique identifier in the URL string. We specify the assetmeter key as an array of meters associated with the asset. For this example, we are only updating a single meter against the asset (Outlet Pressure). In our object, we specify the Meter Name and New Reading value. The linearassetmeterid key with a value of 0 is necessary due to that field being part of the unique identifier on the ASSETMETER table. Values such as the New Reading Date and Inspector will default based on the current date and the logged in user credentials, but can also be specified explicitly in the message. Please feel free to leave questions or comments below. Good luck in your IoT journey!

Share This

Related Posts

ibm_mxmobile_maximo mobile_app_application_suite_report_maintenance_reliability_industry_4_work_order_enterprise_asset_management_inventory_perform_count_log_time_create_meter_reading_shipping_and_recieving_mobility_admin_service_request_issue_parts_material_approve_task_job_plan_software_upgrade
MxMobile Update May 2023 Release
As an IBM Maximo mobile solution provider, A3J Group consistently improves the functionality and features...
integration-trobleshooting-IBM-Maximo-A3J-Group-Consulting-e1636065766665
Workflow Delegates
Pretend you are going to take a real vacation, two weeks in Spain with no work laptop. You have planned...
ibm_mxmobile_maximo mobile_app_application_suite_report_maintenance_reliability_industry_4_work_order_enterprise_asset_management_inventory_perform_count_log_time_create_meter_reading_shipping_and_recieving_mobility_admin_service_request_issue_parts_material_approve_task_job_plan_software_upgrade
MxMobile Update April 2023 Release
A3J Group is happy to announce the latest MxMobile releases below. The releases will be available on...

9 Responses

9 Comments

  1. hi
    when i send maximo update through rest api using
    external system,publish channel and end point,
    the json in update be like (contain rowstamp)
    {
    “_id”: “R18867-RAM”,
    “_rowstamp”: “767476799”,
    “description”: “az”,
    “href”: “https:\/\/flsmidth.maximo.com\/maximo\/oslc\/os\/createpr\/_UjE4ODY3L1JBTQ–“,
    “orgid”: “ACC”,
    “pr1”: “QC”,
    “prnum”: “R18867”,
    “siteid”: “RAM”,
    “status”: “NEW”,
    “status_description”: “New PR”
    }

    i need not to add rowstamp, i found proerty called _Urs, but i don’t know how to use till now,
    please help if you know

    • For outbound publish channel messages, you should be able to use Maximo’s JSON Mapping application to transform the JSON payload to a format that your external system understands.

  2. im tryng to post this with postman
    maxrest/oslc/os/mxwomobile/46693?lean=1

    { assetmeter:
    [ { metername: ‘KEBOCORANMINYAK’,
    assetnum: ‘877618’,
    siteid: ‘TND’,
    newreadingdate: ‘2020-08-13T08:43:34’,
    newreading: ‘Bersih’,
    inspector: ‘INSPEKSI.LUWUK’,
    linearassetmeterid: 0 },
    { metername: ‘KONDISIFISIK’,
    assetnum: ‘877618’,
    siteid: ‘TND’,
    newreadingdate: ‘2020-08-13T08:46:30’,
    newreading: ‘Cacat Sirip Major’,
    inspector: ‘INSPEKSI.LUWUK’,
    linearassetmeterid: 0 }]}

    but i get return 400 like this

    {
    “Error”: {
    “reasonCode”: null,
    “message”: “oslc#create_on_updateuri”,
    “statusCode”: “400”
    }
    }

    please help me

    • The issue is the last element in your URL. It needs to be the REST ID of the Asset record you’re trying to update.

      In the article’s example, the /_QkVERk9SRC8xMTQ1MA== represents a unique identifier for an Asset record that can be referenced in the MXASSET Object Structure. This identifier can be found be querying for the asset using an HTTP GET to the same MXASSET Object Structure, or it can be derived by base64 encoding the asset’s ASSETNUM + “/” + SITEID and prefixing that string with an underscore (“_”) character.

  3. Hello, thank you very much for this!
    Using what you say I’m trying to do a POST to os/mxincident however I’m having troubles just to get a response status = 200.
    I executed this two requests:
    POST: https://host_url//maximo/oslc/os/mxincident/ticketuid I get 400 with the message “oslc#create_on_updateuri”
    POST: https://host_url//maximo/oslc/os/mxincident/ticketid I get 500 with the message “For input string: \”IN41321576\””

    I don’t know what else to try… Do you have an advice to give me, please?

    • The issue is the last element in your URL. It needs to be the REST ID of the Incident record you’re trying to update.

      In the article’s example, the /_QkVERk9SRC8xMTQ1MA== represents a unique identifier for an Asset record that can be referenced in the MXASSET Object Structure. This identifier can be found be querying for the asset using an HTTP GET to the same MXASSET Object Structure, or it can be derived by base64 encoding the asset’s ASSETNUM + “/” + SITEID and prefixing that string with an underscore (“_”) character.

  4. Thanks for this, was playing with python and noticed params needed the ‘spi’ in front? Seems to work now, with API key this way, was unsure if there was a difference. Great trick with the unique identifier!
    ——-
    import config
    import requests
    from requests.packages.urllib3.exceptions import InsecureRequestWarning

    meterread=’100.00′ #your new reading, can put in params to json too
    apikey= ‘apikeyxxxxxxxxxx’

    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

    host = ‘https:/host_url/maximo’ #dev
    url=’/maximo/oslc/os/mxasset’
    url = host + url #renamed for DEV.Testing

    headers = {
    ‘apikey’: apikey,
    ‘properties’: ‘*’,
    ‘Content-Type’: “application/json”,
    ‘x-method-override’: ‘PATCH’,
    ‘patchtype’: ‘MERGE’
    }
    params = {

    ‘oslc.select’: ‘assetuid’,
    ‘oslc.where’: ‘assetnum=12345’ #return the unique identifier from asset num
    }

    r=requests.get(url, headers=headers, params=params,verify=False)
    x=r.json()
    uniqueid= (x[‘rdfs:member’][0][‘rdf:about’]) #get the unique identifier in the URL string

    url=uniqueid #unique identifier in the URL string.
    params = {

    “spi:assetmeter”: [
    {
    ‘spi:inspector’ : ‘JOEY’,
    ‘spi:newreadingdate’ :’&SYSDATE&’,
    “spi:metername”: “FLOAT”,
    “spi:linearassetmeterid”: 0,
    “spi:newreading”: meterread #from ‘meterread=’100.00′ #your new reading’

    }
    ]
    }
    r=requests.post(url, headers=headers, json=params,verify=False)
    pprint(r.status_code)

    • Nice! You can use the lean=1 query parameter to avoid having to include the namespace prefixes.

      In your HTTP GET you can include ‘lean’: ‘1’ in your params object. That should allow you to drop the rdfs: and rdf: prefixes from the initial response. Then you can append a ‘?lean=1’ to the HTTP POST and drop the spi: prefixes from the body of the request.

  5. Using POSTMAN, I am able to post the data and receive 200. But, the meter readings are not updating as expected. I am bale to update the same meter readings with MXMETERDATA. Any suggestions?

    Thanks-


Add a Comment