14 Replies Latest reply on May 3, 2017 11:38 PM by ahawaldar Branched from an earlier discussion. Branched to a new discussion. RSS
    ahawaldar Apprentice

    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

      • Re: How to write custom service in thingworx?
        supandey Collaborator

        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.

          • Re: How to write custom service in thingworx?
            ahawaldar Apprentice

            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

              • Re: How to write custom service in thingworx?
                supandey Collaborator

                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!

                  • Re: How to write custom service in thingworx?
                    ahawaldar Apprentice

                    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

                      • Re: How to write custom service in thingworx?
                        supandey Collaborator

                        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.

                          • Re: How to write custom service in thingworx?
                            ahawaldar Apprentice

                            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

                              • Re: How to write custom service in thingworx?
                                supandey Collaborator

                                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

                                  • Re: How to write custom service in thingworx?
                                    ahawaldar Apprentice

                                    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

                                      • Re: How to write custom service in thingworx?
                                        supandey Collaborator

                                        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

                                          • Re: How to write custom service in thingworx?
                                            ahawaldar Apprentice

                                            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)

                                            • Re: How to write custom service in thingworx?
                                              ahawaldar Apprentice

                                              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());

                                                }

                                               

                                               

                                                }

                                               

                                               

                                              }

                                                • Re: How to write custom service in thingworx?
                                                  supandey Collaborator

                                                  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();
                                                    }
                                                    }
                                                  
                                                  
                                                  }
                                                  
                                                    • Re: How to write custom service in thingworx?
                                                      ahawaldar Apprentice

                                                      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);

                                                           }

                                                              }

                                                      }

                                • Re: How to write custom service in thingworx?
                                  ahawaldar Apprentice

                                  Hi Sushant Pandey,

                                   

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

                                   

                                  Thanks,

                                  Azim