Start Creating a Thingworx Service
Thingworx services are what do the work behind the scenes, providing the glue that results in the bindings that power Mashups and reports.
It is not unusual to be in a position where new or modified services are required to be implemented on a production server environment. It is always good practice to create and test on a development instance, but the risk involved in migrating to live is never zero.
Some risk-reduction practices that will help in the migration process are captured here.
Best practices:
- Edit copies of entities
- Export entities for source control before editing or deleting
- Maintain any custom services in source control and maintain feature branches
- Use Thingworx tags and projects to identify and organize entities containing changes tracked by feature branches
- Use logging to provide visibility to specific features during development and transitions
How to Start
The best way to start writing a new service is to use logging to expose outputs. Services are designed to take multiple inputs but only provide a single output. Logging enables you to trace intermediate steps and ensure you are getting expected results.
Example
What if we wanted to build a table containing a row for each log file received from all devices on the platform?
We need to examine existing services in case there is an entry point in the existing execution flow of services on the platform. For example, if the device entity model (ThingTemplate) contains a service that is called to identify and validate incoming files, we might use this to trigger a log entry each time a log file of a certain type is received by the platform.
We want to take small steps when introducing changes onto a live platform. Initially we should be satisfied with a log entry that simply confirms that the service we are tapping into actually gets called.
I recommend wrapping any log outputs in a try/catch with an error log in case anything unexpected occurs. Concatenate all outputs with the feature name used to identify the project to enable easy log filtering.
To make my logging more consistent I paste in a boilerplate service for logging my feature tests:
logging wrapper
response = false;
logger.info(deviceID + ', ' + flag + ', ' + message);
response = true;
result = response;
Barebones starting example
try {
me.adminLogger({
flag: 'myFeatureName' /* STRING */ ,
message: 'success' /* STRING */
})
catch (e) {
logger.error(me.name + " _ myServiceName: Error in line " + e.lineNumber + ": " + e);
}
Evolved example
try {
var currentDate = new Date();
me.adminLogger({
flag: 'myFeatureName' /* STRING */ ,
deviceID: me.name /* STRING - name of device */,
message: currentDate.toString() /* STRING */
})
catch (e) {
logger.error(me.name + " _ myServiceName: Error in line " + e.lineNumber + ": " + e);
}
When this service is saved, you may need to wait for quite a few seconds for confirmation since a ThingTemplate is inherited by every Thing entity, and the change must cascade to all of them.
Then you can use the script log….
The point of this is…
By logging what we want to put in each row we effectively have created a preview of an infotable or datatable we might want to populate with the data we logged out. We can share it to confirm that it is exactly what is needed and requested. We can gauge the amount of rows accumulated over certain time ranges in case we need to provide additional sorting and filtering and periodic cleanup.