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

Community Tip - You can change your system assigned username to something more personal in your community settings. X

Create service programmatically

jdurand
1-Visitor

Create service programmatically

Hi,

I would like to build a form which will allow users to create services without entering the composer.

So is it possible to create services programmatically without using remote services ?

Regards

ACCEPTED SOLUTION

Accepted Solutions

//

// 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.

View solution in original post

4 REPLIES 4
PaiChung
22-Sapphire I
(To:jdurand)

there is another thread talking about this

Modify service code programmatically

Ok so it is not :/

//

// 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.

Thanks ! It's a perfect explanation and it works.

Announcements


Top Tags