Create a service dynamically

    Disclaimer: example was provided by Hatcher Chad - chad@onfarmsystems.com

      //

      // For this example, we'll have an Math service

      // which takes two numbers, and an operation.

      // The result will be that operation performed on the two inputs.

     

     

      //

      // We either need an Application Key,

      // or user credentials to perform the reads and writes.

      // App keys are a little safer.

      // In this demo, we'll store it on the Entity as a Property.

      var appKey = me.appKey;

     

     

      //

      // The service name needs to be unique and not already in use.

      var serviceName = "MyMath";

     

     

      //

      // What are the inputs to the service?

      // We'll define them nicely here, but manipulate this object later.

      var parameters = {

      "op" : "STRING",

      "x" : "NUMBER",

      "y" : "NUMBER"

      };

     

     

      //

      // What datatype does the service return?

      // If it's an infotable,

      // then you'll also have to specify the data shape

      // as part of the resultType's aspect,

      // but I won't demonstrate that here.

      var output = "NUMBER";

     

     

      //

      // What is the actual service script?

      // We'll define it here as an array of lines, and then join them together.

      var serviceScript = [

      "var result = (function() {",

      " switch(op) {",

      " case \"add\": return x + y;",

      " case \"sub\": return x - y;",

      " case \"mult\": return x * y;",

      " case \"div\": return x / y;",

      " default: return op in Math ? Math[op](x, y) : 0;",

      " };",

      "})();",

      ].join("\n");

     

     

      ////////

     

     

      //

      // Let's convert the friendly parameter definition

      // into the structure that ThingWorx uses:

      var parameterDefinitions = Object.keys(parameters).reduce(function(parameterDefinitions, parameterName, index) {

      var parameterType = parameters[parameterName];

      parameterDefinitions[parameterName] = {

      "name": parameterName,

      "aspects": {},

      "description": "",

      "baseType": parameterType,

      "ordinal": index

      };

      return parameterDefinitions;

      }, {});

     

     

      //

      // Now let's set up our service definition and implementation.

      var definition = {

      "isAllowOverride": false,

      "isOpen": false,

      "sourceType": "Unknown",

      "parameterDefinitions": parameterDefinitions,

      "name": serviceName,

      "aspects": {

      "isAsync": false

      },

      "isLocalOnly": false,

      "description": "",

      "isPrivate": false,

      "sourceName": "",

      "category": "",

      "resultType": {

      "name": "result",

      "aspects": {},

      "description": "",

      "baseType": output,

      "ordinal": 0

      }

      };

     

     

      var implementation = {

      "name": serviceName,

      "description": "",

      "handlerName": "Script",

      "configurationTables": {

      "Script": {

      "isMultiRow": false,

      "name": "Script",

      "description": "Script",

      "rows": [{

      "code": serviceScript

      }],

      "ordinal": 0,

      "dataShape": {

      "fieldDefinitions": {

      "code": {

      "name": "code",

      "aspects": {},

      "description": "code",

      "baseType": "STRING",

      "ordinal": 0

      }

      }

      }

      }

      }

      };

     

     

      ////////

     

     

      //

      // Here are the URLs we'll need in order to make updates.

      // You can change the thing name ('ServiceModifier' here)

      // to something else.

      // If you use credentials instead of an app key,

      // then you can remove the appKey parameter here,

      // but you'll have to add the username and password

      // to the two ContentLoaderFunctions calls.

      var url = {

      export : "http://127.0.0.1:8080/Thingworx/Things/ServiceModifier?Accept=application/json&appKey="+appKey,

      import : "http://127.0.0.1:8080/Thingworx/Things/ServiceModifier?appKey="+appKey

      };

     

     

      //

      // We can download the entity to modify as a JSON object.

      // Older versions of ThingWorx might not support this.

      var config = Resources.ContentLoaderFunctions.GetJSON({

      url : url.export,

      });

     

     

      //

      // We have to modify both the 'effectiveShape',

      // as well as the 'thingShape'.

      config.effectiveShape.serviceDefinitions[serviceName] = definition;

      config.effectiveShape.serviceImplementations[serviceName] = implementation;

     

     

      config.thingShape.serviceDefinitions[serviceName] = definition;

      config.thingShape.serviceImplementations[serviceName] = implementation;

     

     

      // Finally, we can push our updates back into ThingWorx.

      Resources.ContentLoaderFunctions.PutText({

      url : url.export,

      content : JSON.stringify(config),

      contentType : "application/json",

      });

     

     

      // The end.