Unlike local services that execute on the ThingWorx Platform, remote services execute on your device. Remote services can be executed just like local services. However, their input and output definitions and implementation are defined by your edge application.
You can easily pull remote services onto your Thing on the ThingWorx Platform by navigating to the Services tab and clicking Browse Remote Services.
Service definitions describe actions or operations that the ThingWorx Platform can call on the Virtual Thing. A service may have several or no inputs but only one result. The most effective and maintainable way to define services is with annotations (listed below). Both declarative and explicit code examples are outlined.
Annotation | Usage |
---|
ThingWorxServiceDefinition | Add this annotation to a method to indicate that this is a service that the ThingWorx Platform can use. • name — A label for the service. | This name must match the name of the Java method. |
• description — An explanation of the action or operation provided by the service. |
ThingWorxServiceResult | Add this annotation to a method to indicate the result of the service. • name — A label for the result for the ThingWorx Platform to use when presenting the result. This name should always be result and a constant is defined for it: CommonPropertyNames.PROP_RESULT. • description — Explanatory information for the result. | To indicate a void result, use the base type, NOTHING. |
|
ThingWorxServiceParameter | Append this annotation to each input parameter. • name — A label for the parameter. • description — Explanation of the parameter. |
The SteamSensor application provides several services. The first service add two numbers:
@ThingworxServiceDefinition(name = "AddNumbers", description = "Add Two Numbers")
@ThingworxServiceResult(name = CommonPropertyNames.PROP_RESULT, description = "Result",
baseType = "NUMBER")
public Double AddNumbers(
@ThingworxServiceParameter(name = "a", description = "Value 1",
baseType = "NUMBER") Double a,
@ThingworxServiceParameter(name = "b", description = "Value 2",
baseType = "NUMBER") Double b)
throws Exception {
return a + b;
}
The next two services start and stop creating log files:
@ThingworxServiceDefinition(name = "StartLogging", description = "starts creating local log files.")
@ThingworxServiceResult(name = CommonPropertyNames.PROP_RESULT, description = "Result",
baseType = "NOTHING")
public void StartLogging() throws Exception {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
ch.qos.logback.classic.Logger logger = loggerContext.getLogger("ROOT");
logger.addAppender(fileLogAppender);
LOG.info("Started Logging to File.");
}
@ThingworxServiceDefinition(name = "StopLogging", description = "stops creating local log files.")
@ThingworxServiceResult(name = CommonPropertyNames.PROP_RESULT, description = "Result",
baseType = "NOTHING")
public void StopLogging() throws Exception {
LOG.info("Stopped Logging to File.");
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
ch.qos.logback.classic.Logger logger = loggerContext.getLogger("ROOT");
logger.detachAppender("ROLLING");
}
The following service retrieves a string value for a property:
@ThingworxServiceDefinition(name = "GetBigString", description = "Get big string")
@ThingworxServiceResult(name = CommonPropertyNames.PROP_RESULT, description = "Result",
baseType = "STRING")
public String GetBigString() {
StringBuilder sbValue = new StringBuilder();
for (int i = 0; i < 24000; i++) {
sbValue.append('0');
}
return sbValue.toString();
}
The last service shuts down the client:
@ThingworxServiceDefinition(name = "Shutdown", description = "Shutdown the client")
@ThingworxServiceResult(name = CommonPropertyNames.PROP_RESULT, description = "",
baseType = "NOTHING")
public synchronized void Shutdown() throws Exception {
// Should not have to do this, but guard against this method being called more than once.
if (this._shutdownThread == null) {
// Create a thread for shutting down and start the thread
this._shutdownThread = new Thread(this);
this._shutdownThread.start();
}
}
To run the Shutdown service, the SteamSensor example uses the following code:
@Override
public void run() {
try {
// Delay for a period to verify that the Shutdown service will return
Thread.sleep(1000);
// Shutdown the client
this.getClient().shutdown();
} catch (Exception x) {
// Not much can be done if there is an exception here
// In the case of production code should at least log the error
}
}
}