More...

Embedded Web Service : The Universal Remote Interface.

D-TACQ ACQ196CPCI and ACQ216CPCI networked digitizers provide a dedicated Web Service interface for remote control. The webservice allows easy integration with modern software on a variety of platforms, including Microsoft .NET and Labview.

The webservice offers both simple shell command (Low Level) and high level (Application) interfaces, provides remote procedure call and object passing facilities using the SOAPworld protocol. The interface is fully defined using WSDLworld.

The embedded web service is implemented in C++ using the excellent gSOAPworld package.
Examples of the WSDLworld : Low Level / Application.
Full source code is provided to both client and server sides of the package, known as "SOAPI".
Code (.tgz) : SOAPI / (VC++ project) / documentation

The Low Level Interface allows for a remote client to execute shell commands on the target. This enabled remote applications to run shell scripts on the target, which in turn can control every aspect of capture. Examples of clients that are current available to use the Low Level interface include examples written in VB.NET and Perl (Soap::Lite).
A complete list of the low level commands can be found in 2GUG.

The Application Interface extends the simple interface to allow a remote client to program the card to an API at the functional level. The API provides for a series of Transaction objects to set various high level parameters on the device. The Full interface has been implemented using a gSOAPworld client, tested on both Linux and Windows. The example code includes a "Test Loop" application that will take the card through a sequence of captures, changing capture parameters each time.

Components of the SOAPI client software

- library and programs run the same way on all supported platforms.

  • API library
  • acq2sh - remote shell interface
  • acqcmd - emulates traditional acqcmd interface
  • acq2script - remote shell program for remote scripting with per line status checking, stops on first error.
  • acq2xx_api_test functional test app using Application layer.




Use Cases

  • When to use SOAP: for control of transient captures and general system setup, maximum command rate ~25/sec, practical shot rate about 0.5Hz. Typical use case is a 10s shot, followed by 100s data upload.
  • Excellent for distributed networking, strong cross-platform and integration capability.
  • The Low Level interface will allow any client software to control the card by following example commands from 2GUG. If the client software has built in Web Service support, then the interface can be controlled directly, and in some case this can be done with very little effort (see VB.NET, Perl examples below). The client software can also spawn the supplied "acq2sh" application to run a remote command script, or it will be possible to call into the supplied SOAPI library.
  • The High Level interface has only been tested on C++ clients linked to the SOAPI library.
  • When NOT to use SOAP: for high repetition rate and control applications. D-TACQ has a number of solutions using low latency transfers on the CPCI backplane to meet this need.
  • SOAP is NOT used for data upload. Recommended use case is to submit "Target Push" upload instructions to the card using the low level interface. A typical upload instruction could invoke cURLworld on the card to upload channel data from a virtual file to a remote ftp or http server. A call to the MDSplusworld Thin Client would also be appropriate here.


Alternatives

  • dt100rc - D-TACQ's cross platform remote client is recommended for interactive use - see resources page.
  • dt100d - remote access on TCP/IP socket - effectively the same service offered by the Low Level Web Service presented above, but the onus is on the developer to handle the networking code. For a full description of the dt100d remote service, please refer to 2GUG # 7.2.

Possible Extensions

  • Possibility of secure operating using SSL. Normal use for this system is on a secure internal network, or "Ethernet Field Bus".
  • Possibility of transient data upload using MTOM.
  • Possibility of streaming data upload using MTOM.



Example: VB.NET remote shell command client


Module Module1

Sub Main()
'autogenerated from web reference http://acq196_001/cgi-bin/acq2sh.wsdl
Dim service As New acq196_001.acq2xx
Dim result As String
Dim command As String

'a more practical example might read commands from script file
command = "acqcmd setInternalClock 500000;acqcmd setArm"
result = service.acq2sh(command)
System.Console.Out.WriteLine("command: " + command)
System.Console.Out.WriteLine("result : " + result)
End Sub

End Module



Example: Perl Soap::Lite remote shell command client


#!/usr/bin/perl

use SOAP::Lite;

my $URL = 'http:///acq196_001/cgi-bin/acq2sh.wsdl
my $shellcmd = 'acqcmd setInternalClock 500000;acqcmd setArm';

my $service = SOAP::Lite->service($URL);
my $command = SOAP::Data->name('command' => $shellcmd);

my $result = $service->acq2sh($command);

print 'command:' . $command . "\n";
print 'result :' . $result . "\n";



Example: High level application client Test Loop (C++)


int loop_test(char *URL)
/** highly artificial test case - capture 100 shots, with incrementing
* sample count.
* best way to view this test is to run an dt100rc concurrently,
* allow dt100rc to sit in the "Control" page polling status.
* @param URL server URL eg "http://acq196_002:66666"
*/
{
int rc =0;
soap* soap = soap_new();

acq2xx__InternalClockSetTransaction clockSet(250000);
acq2xx__SignalSetTransaction trigSet("trig", DI_NONE);

for (int shot = 0; shot < maxshots; ++shot, post1 += increment){

acq2xx__ModeSetTransaction modeSet(MODE_SOFT_TRANSIENT, 0, post1);
acq2xx__AcqControlTransaction acqControl(&modeSet, &clockSet, &trigSet, 0);

/* submit one composite transaction to make multiple settings in one
* efficient network transaction
*/
rc = runTransaction(soap, URL, &acqControl);
dierr(rc, acqControl);


acq2xx__AcqStatus status;
/* make remote procedure calls first to ARM the card, then poll for completion */
rc = soap_call_acq2xx__setArm(soap, URL, "", 0, status);
dierr(rc, "setArm");

do {
rc = soap_call_acq2xx__waitStop(soap, URL, "", 10, status);
dierr(rc, "waitStop");
}
while(status.state != ST_STOP);

cout << "shot:" << shot << " numsamples:" << status.postlen << endl;
}

soap_destroy(soap);
soap_end(soap);
soap_done(soap);
return rc;
}