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

Community Tip - Help us improve the PTC Community by taking this short Community Survey! X

How to write custom service in thingworx?

ahawaldar
1-Newbie

How to write custom service in thingworx?

Hi Sushant Pandey​ / Ankit Gupta​,

How can I write custom service in thingworx? What I want to implement is for data coming into the platform I need to apply FFT algorithm which can be easily done by using java library. One such open source library is by Apache. Please let me know how can I use this java library and show the data on mash up?

Thanks,

Azim.

Message was edited by: Sushant Pandey branched from https://community.thingworx.com/message/56939#56939

14 REPLIES 14
supandey
19-Tanzanite
(To:ahawaldar)

Hi Azim, remembering from your other post How to show Fast Fourier transform for a set of readings from accelerometer in mash up? you plan to use the Java SDK therefore the easiest option for you which I can think off right away would be to create a virtual thing via ThingWorx Java SDK. This will hold your service ​and other properties built using the Java libraries you need for implementing your algorithm. Your actual hardware/device will send data to this virtual thing containing the service to process that data. Once the post processing is done you can then connect to a Thing created out of RemoteThing in ThingWorx Composer via the ConnectedThingClient Component​ your processed data to ThingWorx.

The other option could be that you create an extension using ThingWorx Extension (based off Java SDK) (also there's an  Eclipse Plugin available for ThingWorx Extension )this will contain all the java libraries and services you created for processing the data within ThingWorx using your custom services -finally import this custom extension in ThingWorx so you get all the required services and so on to process the data coming in directly from the hardware/device to ThingWorx.

Hope this helps.

Hi Sushant Pandey​,

Thanks for the help. Since FFT algorithm is huge operation, performing this at Java SDK layer which will eventually be installed at a gateway is not a preferred way of doing.  However I can go with other option which is Thingworx Extension. I will go through this and let you know on how I proceed.

Thanks,

Azim

supandey
19-Tanzanite
(To:ahawaldar)

Sure, I'm not aware of your product architecture but from what you mentioned above sure Extension sounds the way to go for you.

Good luck!

Hi Sushant Pandey​,

I started with the implementation. Let me tell you my use case. Every second around 50 sets of data will be pumped into the platform. Basically I need to use baseType as array. I have seen some baseType in thingworx such as NUMBER,STRING. But, I have not seen ARRAY so which baseType is suitable for arrays?

Thanks,

Azim

supandey
19-Tanzanite
(To:ahawaldar)

Azim to begin with you might want to check the list of available baseTypes for ThingWorx. I'm thinking for your purpose Infotable could be a good fit, if you haven't already checked this there is a great documentation on Getting to Know InfoTables.pdf

Hope this would help.

Hi Sushant Pandey​,

I thought of using infotable. But this did not helped me. I have data something like below.

[-0.039, -0.017, -0.098, -0.161, -0.129, -0.061, -0.132, -0.107, -0.032, -0.044, -0.117, -0.161, -0.117, -0.142, -0.068, -0.049, -0.046, -0.105, -0.012, -0.081, -0.012, -0.061, -0.059, -0.029, -0.049, -0.066, -0.095, -0.117, -0.132, -0.125, -0.088, -0.154, -0.164, -0.159, -0.151, -0.188, -0.122, -0.046, -0.027, 0.012, -0.039, -0.061, -0.12, -0.088, -0.081, -0.093, -0.076, -0.115, -0.103, -0.134, -0.112, -0.139, -0.229, -0.12, -0.122, -0.103, -0.237, -0.095, 0.0, -0.063, -0.093, -0.178, -0.029, -0.051]

Any help for me here how can I use infotable for above data.

Thanks,

Azim

supandey
19-Tanzanite
(To:ahawaldar)

Could you elaborate how you tried using Infotable?

If that's how the  data looks like for you, create a DataShape with a field and then create an Infotable using that Datashape just to give you an e.g.

var params = {

  infoTableName : "InfoTable",

  dataShapeName : "DemoDS"

};

// CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(DemoDS)

var result = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);

and that's how datashape looks like

Once you have Infotable created you could use the Create infotable entry from datashape, like so

// DemoDS entry object

var newEntry = new Object();

newEntry.Field1 = undefined; // NUMBER

and you can go on calling this to add the entries one after the another in that Infotable

Hi Sushant Pandey​,

I am working on java SDK . Java SDK will read the array of data per second and send it to platform.

so My virtual thing will be as below

@ThingworxPropertyDefinitions(

  properties={

  @com.thingworx.metadata.annotations.ThingworxPropertyDefinition(name="Prop_Xaxis", description="Xaxis reading of bearing1", baseType="INFOTABLE", aspects={"dataChangeType:ALWAYS", "dataChangeThreshold:0", "cacheTime:0", "isPersistent:FALSE", "isReadOnly:TRUE", "pushType:VALUE"}),

  @com.thingworx.metadata.annotations.ThingworxPropertyDefinition(name="Prop_Yaxis", description="Yaxis reading of bearing1", baseType="INFOTABLE", aspects={"dataChangeType:ALWAYS", "dataChangeThreshold:0", "cacheTime:0", "isPersistent:FALSE", "isReadOnly:TRUE", "pushType:VALUE"}),

                   }

  )

public class WheelThing extends VirtualThing

So when I set an array of for above properties it throws error.

Thanks,

Azim

supandey
19-Tanzanite
(To:ahawaldar)

Where are you setting the Datashape for your Infotable? What's the error? Please run through the debugging steps in your code to narrow down on the cause. You can always refer to the sample code provided with the  Java SDK to better your understanding.

With above code you are simply creating properties with infotable base type and having aspect set to not persistent you will not have those values stored in ThingWorx which is file if you don't intend to store those values which you receive from your device, but you intend to save it make sure to mark isPersistent as true

Below is the error message which I am getting

Exception in thread "main" java.lang.Exception: Unable To Convert From [D to INFOTABLE

  at com.thingworx.types.BaseTypes.generateConversionException(BaseTypes.java:596)

Hi Sushant Pandey​,

Now I have defined DataShape and info table. The property values are being read into infotable. However these values are not pushed to platform. When debugged the code, what I found was the updateSubscribedProperties(10000);  was not running as expected. The reason for that was the first line of the code in method updateSubscribedProperties  always returned false since  getPendingPropertyUpdates().size() being zero. Anything you can suggest me . Below is my code.

@ThingworxPropertyDefinitions(

  properties={

  @com.thingworx.metadata.annotations.ThingworxPropertyDefinition(name="Prop_acceleration", description="Xaxis reading of bearing1", baseType="INFOTABLE", aspects={"dataChangeType:ALWAYS", "dataChangeThreshold:0", "cacheTime:-1", "isPersistent:TRUE", "isReadOnly:TRUE", "pushType:VALUE"})

  }

  )

public class WheelThing extends VirtualThing {

  /**

  *

  */

  private static final long serialVersionUID = -3419672881497640537L;

  Random randomGenerator;

  boolean ranScanOnce = false;

  int xAxisColumn;

  int yAxisColumn;

  public WheelThing(String name, String description, ConnectedThingClient client)

  {

  super(name, description, client);

  initializeFromAnnotations();

  this.randomGenerator = new Random();

  xAxisColumn = 0;

  yAxisColumn = 1;

  }

  public void processScanRequest()

  throws Exception

  {

  super.processScanRequest();

  scanDevice();

  }

  public void scanDevice()

  throws Exception

  {

  DataShapeDefinition dsd = new DataShapeDefinition(); 

  dsd.addFieldDefinition(new FieldDefinition("xaxis", "STRING")); 

  dsd.addFieldDefinition(new FieldDefinition("yaxis", "STRING")); 

  InfoTable it = new InfoTable(dsd); 

  constructInfoTable(it,xAxisColumn,yAxisColumn);

  setProperty("Prop_acceleration",it);

  this.ranScanOnce = true;

  updateSubscribedProperties(10000);

  }

  private void constructInfoTable(InfoTable it, int xAxisColumn2, int yAxisColumn2) throws Exception {

  Workbook wb = WorkbookFactory.create(new FileInputStream("D:\\projects\\geardata\\bearing_IMS\\1st_test\\1st_test\\2003.10.22.12.06.xlsx"));

  Sheet sheet = wb.getSheetAt(0);

  ValueCollection rowValue = new ValueCollection();

  for (int j=0; j< 63+ 1; j++) {

  Row row = sheet.getRow(j);

  Cell xcell = row.getCell(xAxisColumn2); //get first cell

  System.out.println("x axis:"+xcell.getNumericCellValue());

  Cell ycell = row.getCell(yAxisColumn2);

  System.out.println("y axis:"+ycell.getNumericCellValue());

  rowValue.SetStringValue("xaxis", new StringPrimitive(String.valueOf(xcell.getNumericCellValue()))); 

  rowValue.SetStringValue("yaxis", new StringPrimitive(String.valueOf(ycell.getNumericCellValue()))); 

  it.addRow(rowValue.clone());

  }

  }

}

supandey
19-Tanzanite
(To:ahawaldar)

Azim you mentioned that the properties are not getting pushed, the code you have shared doesn't include the ClientConfigurator part. Not sure if you already have that, if not you will need it to open the WS to initiate the connection from your virtual thing to the remoteThing in the ThingWorx platform.

Here's something how i do to update

public class ClinetConfigurator {

  private static final Logger LOG = LoggerFactory.getLogger(ClientConfigurator.class);

  public static Random random = new Random();

  public static void main(String[] args) {

  try {

  // Setting the server URL and the appkey to enable this client to

  // connect to the ThingWorx platform

  //TWX server URI

  String serverURL = "ws://localhost:8080/Thingworx/WS";

  //Applicaton server appKey

  String appKey = "8b09fb4f-73aa-4008-bce3-28e2a26ae43a";

  // configure client

  ClientConfigurator config = new ClientConfigurator();

  config.setUri(serverURL);

  config.setAppKey(appKey);

  config.getSecurityClaims().addClaim(appKey, appKey);

  // connected to client

  ConnectedThingClient client = new ConnectedThingClient(config, null);

  // start the client

  client.start(); // Async - doesn't always mean that the client has

  // started immediately when the method is called

  //create and bind the virtual thing to the platform

  TractorVirtualThing tractorThing = new TractorVirtualThing("GreenCo.Tractor1", "A virtual thing", client);

  LOG.debug("Binding to " + serverURL + "to register thing" + tractorThing.getName());

  // binding happens just once with 1 connection

  client.bindThing(tractorThing);

  LOG.debug("Connecting to " + serverURL + "using key" + appKey);

  //

  while (true) {

  if(client.getEndpoint().isConnected()) {

  tractorThing.processScanRequest();

  }

  Thread.sleep(60000); // cycles miliseconds

  }

  } catch (Exception e) {

  // Catching the exception when bind fails

  LOG.error("An error occured", e);

  e.printStackTrace();

  }

  }

}

Hi Sushant Pandey​,

The connection is established I can see that isConnected property as true. The data is not pumped into the thingworx platform because updateSubscribedProperties(10000);  was not running as expected. The reason for that was the first line of the code in method updateSubscribedProperties  always returned false since  getPendingPropertyUpdates().size() being zero. The client code is as below.

public class WheelThingClient extends ConnectedThingClient {

   private static final Logger LOG = LoggerFactory.getLogger(RollingStockClient.class);

  public static Random random = new Random();

  public WheelThingClient(ClientConfigurator config) throws Exception {

  super(config,null);

  // TODO Auto-generated constructor stub

  }

   public static void main(String[] args)

     throws Exception

   {

   int scanRate = 30000;

  boolean valueRead = false;

     MasterClientConfigurator masterconfig = new MasterClientConfigurator(args);

     WheelThingClient client = new WheelThingClient(masterconfig.config);

    WheelThing rollingStockThing = new WheelThing("WheelThing", "WheelThing", client);

    

     client.bindThing(rollingStockThing);

     try

     {

      System.out.println(masterconfig);

       client.start();

     }

     catch (Exception eStart)

     {

       System.out.println("Initial Start Failed : " + eStart.getMessage());

     }

     while (!client.isShutdown())

     {

       if (client.getEndpoint().isConnected()) {

       if(!valueRead) {

       rollingStockThing.processScanRequest();

       Thread.sleep(random.nextInt(300));

       }

       valueRead = true;

      

       }

       Thread.sleep(scanRate);

     }

        }

}

Hi Sushant Pandey​,

Waiting for your reply? I am not able to proceed . Please help.

Thanks,

Azim

Top Tags