cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Have a PTC product question you need answered fast? Chances are someone has asked it before. Learn about the community search. X

Axeda: Finding current and historical Dataitems for all Assets in a Model

No ratings

import com.axeda.drm.sdk.Context

import com.axeda.drm.sdk.device.ModelFinder

import com.axeda.drm.sdk.device.Model

import com.axeda.drm.sdk.device.DeviceFinder

import com.axeda.drm.sdk.data.CurrentDataFinder

import com.axeda.drm.sdk.device.Device

import com.axeda.drm.sdk.data.HistoricalDataFinder

import net.sf.json.JSONObject

/*

* DataItemEachDevice.groovy

*

* Find the current data item and historical data items for all assets in a given model.

*

* @param model_name        -   (REQ):Str name of the model.

* @param data_item_name    -   (REQ):Str name of the data item to query on.

* @param from_time         -   (REQ):Long millisecond timestamp to begin query from.

* @param to_time           -   (REQ):Long millisecond timestamp to end query at.

*

* @note from_time and to_time should be provided because it limits the query size.

*

* @author Sara Streeter <sstreeter@axeda.com>

*/

def response = [:]

// measure the script run time

def timeProfiles = [:]

def scriptStartTime = new Date()

try {

// getUserContext is supported as of release 6.1.5 and higher

    final def CONTEXT = Context.getUserContext()

// confirm that required parameters have been provided

    validateParameters(actual: parameters, expected: ["model_name", "data_item_name", "from_time", "to_time"])

// find the model

    def modelFinder = new ModelFinder(CONTEXT)

    modelFinder.setName(parameters.model_name)

    Model model = modelFinder.findOne()

// throw exception if no model found

    if (!model) {

        throw new Exception("No model found for ${parameters.model_name}.")

    }

// find all assets of that model

    def assetFinder = new DeviceFinder(CONTEXT)

    assetFinder.setModel(model)

    def assets = assetFinder.findAll()

// find the current and historical data values for each asset

//note: since device will be set on the datafinders going forward, a dummy device is set on instantiation which is not actually stored

    def currentDataFinder = new CurrentDataFinder(CONTEXT, new Device(CONTEXT, "placeholder", model))

    def historicalDataFinder = new HistoricalDataFinder(CONTEXT, new Device(CONTEXT, "placeholder", model))

    historicalDataFinder.startDate = new Date(parameters.from_time as Long)

    historicalDataFinder.endDate = new Date(parameters.to_time as Long)

// assemble the response

    assets = assets.collect { Device asset ->

        currentDataFinder.device = asset

        def currentValue = currentDataFinder.find(parameters.data_item_name)

        historicalDataFinder.device = asset

        def valueList = historicalDataFinder.find(currentValue?.dataItem)

        [

                id: asset.id.value,

                name: asset.name,

                serialNumber: asset.serialNumber,

                model: [id: asset.model.id.value, name: asset.model.name],

                current_data: currentValue.asString(),

                historical_data: valueList.collect { [timestamp: it.getTimestamp().format("yyyyMMdd HH:mm"), value: it.asString()] }

        ]

    }

    response = [result: [items: assets]]

} catch (def ex) {

    logger.error ex

    response += [

            error: [

                    type: "Backend Application Error", msg: ex.getLocalizedMessage()

            ]

    ]

}

finally {

// create and output the running time profile

    timeProfiles << createTimeProfile("DataItemEachDevice", scriptStartTime, new Date())

    response += [params: parameters, meta: [:], timeProfiles: timeProfiles]

}

return ['Content-Type': 'application/json', 'Content': JSONObject.fromObject(response).toString(2)]

private Map createTimeProfile(String label, Date startTime, Date endTime) {

    [

            (label): [

                    startTime: [timestamp: startTime.time, readable: startTime.toString()],

                    endTime: [timestamp: endTime.time, readable: endTime.toString()],

                    profile: [

                            elapsed_millis: endTime.time - startTime.time,

                            elapsed_secs: (endTime.time - startTime.time) / 1000

                    ]

            ]

    ]

}

private validateParameters(Map args) {

    if (!args.containsKey("actual")) {

        throw new Exception("validateParameters(args) requires 'actual' key.")

    }

    if (!args.containsKey("expected")) {

        throw new Exception("validateParameters(args) requires 'expected' key.")

    }

    def config = [

            require_username: false

    ]

    Map actualParameters = args.actual.clone() as Map

    List expectedParameters = args.expected

    config.each { key, value ->

        if (args.options?.containsKey(key)) {

            config[key] = args.options[key]

        }

    }

    if (!config.require_username) { actualParameters.remove("username") }

    expectedParameters.each { paramName ->

        if (!actualParameters.containsKey(paramName) || !actualParameters[paramName]) {

            throw new IllegalArgumentException(

                    "Parameter '${paramName}' was not found in the query; '${paramName}' is a reqd. parameter.")

        }

    }

}

Sample Output:

{

  "result": {

    "items": [{

      "id": 4240,

      "name": "ASVM_9",

      "serialNumber": "ASVM_9",

      "model": {

        "id": 1535,

        "name": "SimVM4"

      },

      "current_data": "142.0",

      "historical_data": [{

        "timestamp": "20120331 17:00", "value": "142.0"

      }, {

        "timestamp": "20120331 16:59", "value": "143.0"

      }, {

        "timestamp": "20120331 16:59", "value": "144.0"

      }, {

        "timestamp": "20120331 16:58", "value": "145.0"

      }, {

        "timestamp": "20120331 16:58", "value": "146.0"

      }, {

        "timestamp": "20120331 16:57", "value": "147.0"

      }, {

        "timestamp": "20120331 16:57", "value": "148.0"

      }, {

        "timestamp": "20120330 19:30",

        "value": "0.0"

      }]

    }, {

      "id": 4246,

      "name": "ASVM_12",

      "serialNumber": "ASVM_12",

      "model": {

        "id": 1535,

        "name": "SimVM4"

      },

      "current_data": "138.0",

      "historical_data": [{

        "timestamp": "20120331 17:00",        "value": "138.0"

      }, {

        "timestamp": "20120331 17:00",        "value": "139.0"

      }, {

        "timestamp": "20120331 16:59",        "value": "140.0"

      }, {

        "timestamp": "20120331 16:59",        "value": "141.0"

      }, {

        "timestamp": "20120331 16:59",        "value": "142.0"

      }, {

        "timestamp": "20120331 16:59",        "value": "143.0"

      }, {

        "timestamp": "20120330 19:32",

        "value": "0.0"

      }]

     //

     // MORE ASSETS HERE

     //

    }]

  },

  "params": {

    "username": "sstreeter",

    "from_time": "1332272219000",

    "data_item_name": "CurrentStock",

    "sessionid": "JOQ5I7ofRXYA-RnA37Vk93bRUH718yoFF5 9p0JbCnfyoHolFprf",

    "model_name": "SimVM4",

    "to_time": "1335469008000"

  },

  "meta": {},

  "timeProfiles": {

    "DataItemEachDevice": {

      "startTime": {

        "timestamp": 1335469168725,

        "readable": "Thu Apr 26 19:39:28 GMT 2012"

      },

      "endTime": {

        "timestamp": 1335469180569,

        "readable": "Thu Apr 26 19:39:40 GMT 2012"

      },

      "profile": {

        "elapsed_millis": 11844,

        "elapsed_secs": 11.844

      }

    }

  }

}

Version history
Last update:
‎May 25, 2016 09:56 AM
Updated by:
Labels (2)