App API

While you build an app with the Builder, it automatically creates an API object that will be published as a remote object when the app is run.

The structure of the API object can be manually managed to an extent, but the Builder also makes some automatic changes. Whenever you open an UI component to display or edit a parameter, the Builder will add an API entry to it to make sure the UI component will also work when run remotely.

When designing an API it is important to understand the difference between things that are shared by all clients and those that are not. When an app is started, it will run exactly one instance of the processing graph and publish exactly one instance of the API object, which is therefore shared by all clients. Any change made to the state of that object will be seen by them all and any signal sent can be captured by any of the clients.

Properties

Properties are used to parameterize the execution of the processing graph and thus alter the state of the graph. Once a parameter is set, the effect will be seen by all clients.

When you drop a non-required input parameter on an UI, the Builder will add a property to the API object. This property will be used by the UI component to change the value of the dropped parameter. There will also be a signal that lets other clients to listen to changes of the property.

It is also possible to manually add an input parameter as a property to the API by right-clicking it and selecting "Publish app API property" from the context menu.

Signals

Each output parameter dropped on the UI will create a signal in the API object. This signal can be connected to by anybody, and all clients will receive the same value. The UI component will update its contents whenever a new value is received through the signal.

To manually add an output as a signal to the API object, right-click the parameter and select "Publish app API signal" from the context menu.

Single input functions

Connectable inputs can be individually published as functions in the API. When such a function is called, the function's input argument will be sent to the tool's input as if it was connected to another tool. Any client can call the function, and everybody will also be able to observe the processing results.

It is rarely useful to publish inputs in intermediate tools this way. Doing so is an easy way of locking up the processing graph. Single input functions may however come in handy in situations where you want to provide an external trigger to a processing pipeline by publishing the very first input as a function.

To publish an input parameter as a function, select "Publish app API function" from its context menu.

Tool functions

In applications where the data to be analyzed is sent by the client one usually wants the results to be delivered to the sending client only. In this case, signals are not the correct way of sending the results as they can be connected to by anybody.

It is possible to make any tool in the analysis graph callable as an API function. Such functions differ from single input functions in two important ways:

  1. All input parameters are passed in one call.
  2. The results are delivered using callback functions supplied by the client to the calling client only.

Any tool can be exposed as a function by simply checking the "Publish tool function API" box in the tool's properties (opens from context menu). The dialog lets you to choose which inputs and outputs of the tool are actually published.

The created API function will take three arguments at a minimum:

  • Tool input arguments, one for each published input. There needs to be at least one published input.
  • Success callback function. If the call succeeds, this function will be passed the values of the published outputs.
  • Failure callback function. If the call fails, this function will be passed a string describing the error.

For example, if the binarize tool was published as a function, the signature of the function would be:

binarize: (image: Image,
           level: int,
           invert: bool,
           success: (image: Image),
           failure: (message: String)) -> bool

The first three parameters are the inputs of the binarize tool. The fourth parameter is the success callback function that will be passed an image, which is the output of the tool. The last parameter is the failure callback that will be called with a reason phrase if the call fails.

The API function returns true if the call can be successfully queued. In this case either success or failure will be called sooner or later. If the call cannot be queued, the return value will be false, in which case neither of the callback functions will be invoked.

In JavaScript, calling such a function would happen like this:

const va = VisionAppster;
const apiCtrl = new va.RemoteObject('http://localhost:2015/apis/com.test/1');
apiCtrl.connect().then(api => {
  api.binarize(new va.Image(5, 5, va.Image.Type.Gray8),
               127,
               true,
               image => console.log,
               error => console.log);
});

The example doesn't do anything useful with the result, it just writes either the result image or the error message to the console.

It usually makes no sense to publish a native tool such as the binarize tool. Instead, one usually wants to create a compound that bundles many tools into one and publish that as an API function.

API editor

The properties, functions and signals of the API object are shown in the API editor that opens by clicking the small API icon at the upper right corner of the Builder's workspace. The API editor lets you to change the names of the published API entries and to see which parameters or tools are linked to which entries. Try clicking the names to see where they are linked to.