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 } } } }
View full tip