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

    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
          }
        }
      }
    }