Community Tip - You can change your system assigned username to something more personal in your community settings. X
Hi everyone,
As everyone knows already, the main way to define Properties inside the EMS Java SDK is to use annotations at the beginning of the VirtualThing class implementation.
There are some use-cases when we need to define those properties dynamically, at runtime, like for example when we use a VirtualThing to push a sensor's data from a Device Cloud to the ThingWorx server, for multiple customers.
In this case, the number properties differ based on customers, and due to the large number of variations, we need to be able to define programmatically the Properties themselves.
The following code will do just that:
for (int i = 0; i < int_PropertiesLength; i++) {
Node nNode = device_Properties.item(i);
PropertyDefinition pd;
AspectCollection aspects = new AspectCollection();
if (NumberUtils.isNumber(str_NodeValue))
{
pd = new PropertyDefinition(nNode.getNodeName(), " ", BaseTypes.NUMBER);
}
else if (str_NodeValue=="true"|str_NodeValue=="false")
{
pd = new PropertyDefinition(nNode.getNodeName(), " ", BaseTypes.BOOLEAN);
}
else
pd = new PropertyDefinition(nNode.getNodeName(), " ", BaseTypes.STRING);
aspects.put(Aspects.ASPECT_DATACHANGETYPE, new StringPrimitive(DataChangeType.VALUE.name()));
//Add the dataChangeThreshold aspect
aspects.put(Aspects.ASPECT_DATACHANGETHRESHOLD, new NumberPrimitive(0.0));
//Add the cacheTime aspect
aspects.put(Aspects.ASPECT_CACHETIME, new IntegerPrimitive(0));
//Add the isPersistent aspect
aspects.put(Aspects.ASPECT_ISPERSISTENT, new BooleanPrimitive(false));
//Add the isReadOnly aspect
aspects.put(Aspects.ASPECT_ISREADONLY, new BooleanPrimitive(true));
//Add the pushType aspect
aspects.put("pushType", new StringPrimitive(DataChangeType.ALWAYS.name()));
aspects.put(Aspects.ASPECT_ISLOGGED,new BooleanPrimitive(true));
//Add the defaultValue aspect if needed...
//aspects.put(Aspects.ASPECT_DEFAULTVALUE, new BooleanPrimitive(true));
pd.setAspects(aspects);
super.defineProperty(pd);
}
//you need to comment initializeFromAnnotations() and use instead the initialize() in order for this to work.
//super.initializeFromAnnotations();
super.initialize();
Please put this code in the Constructor method of your VirtualThing extending implementation. It needs to be run exactly once, at any instance creation.
This method relies on the manual discovery of the sensor properties that you will do before this.
Depending on the implementation you can either do the discovery of the properties here in this method (too slow), or you can pass it as a parameter to the constructor (better).
Hope it helps!
Thanks, what about if i want to define a service ? i used this code:
ServiceDefinition serviceDef = new ServiceDefinition("AddNum","Add two numbers");
FieldDefinitionCollection parameterFields = new FieldDefinitionCollection();
parameterFields.addFieldDefinition(new FieldDefinition("p1","The first addend of the operation",BaseTypes.NUMBER));
parameterFields.addFieldDefinition(new FieldDefinition("p2","The second addend of the operation",BaseTypes.NUMBER));
FieldDefinition resultField = new FieldDefinition(CommonPropertyNames.PROP_RESULT,"The sum of the two parameters",BaseTypes.NUMBER); serviceDef.setParameters(parameterFields);
i declared AddNum ouside the main:
public Double AddNum(Double p1, Double p2) throws Exception { return p1 + p2; }
but when bind in thingworx i get : Unable to Invoke Service AddNum on asdasd : Service Handler For [AddNum] Does Not Exist On Thing [SteamSensor9877]
Yes Thanks, i've opened a case and this is the answer