Community Tip - Learn all about the Community Ranking System, a fun gamification element of the PTC Community. X
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
}
}
}
}