The eSTAR Project

Plastic

From EStar

A block diagram showing the prototype event monitor using the Plastic Hub to transport event messages to Plastic-aware applications.
Enlarge
A block diagram showing the prototype event monitor using the Plastic Hub to transport event messages to Plastic-aware applications.

The PLASTIC protocol is a standards effort on the part of the VOTech project, to allow greater intercommuniication betweem astronomical applications. This protocol may in time be put forward to the IVOA for full standardisation.

The eSTAR project is currently involved in the standardisation process and prototyping of various PLASTIC clients, and is in the process of back-porting the emerging standard into the current deployed software to increase the flexibility of the agent framework.

Plastic-enabling Google Sky (Beta)

A block diagram showing the message flow to Plastic-enable Google Sky.
Enlarge
A block diagram showing the message flow to Plastic-enable Google Sky.

As a proof-of-concept we have Plastic-enabled Google Sky using a facade application. It registers with the Plastic Hub as normal and listens for ivo://votech.org/sky/pointAtCoords messages. These are Plastic messages telling interested applications to "point at" an RA & Dec. When such a message is passed through the Hub, say by CDS Aladin, it is forwarded to the facade application, which then builds a KML placemark file. The facade application then exposes this KML file via an embedded web server. If you then point Google Sky at the KML file via a new network link set to periodically update then any RA & Dec points getting passed through the Plastic Hub will start to appear as Placemarks inside Google Sky in more or less real-time.

Also when you send a Plastic message into Google Sky the <Description> tag in the Placemark has a link which, when clicked, will call back to the facade application's embedded webserver and allow you to send a Plastic message back to the Hub. This means we now have bi-directional control, both in and out, of Google Sky with Plastic.

Plastic Monitor Widget

A screenshot of the Dashboard Widget.
Enlarge
A screenshot of the Dashboard Widget.

The fourth Apple Dashboard Widget for Mac OS X Tiger from the eSTAR project. This is the first of several widgets to come out of our work on Plastic.

This is an alpha release which still has some problems when updating the widget while switching between different views. It also currently relies, at least in part, on the undocumented REST interface of the AstroGrid Plastic Hub for the initial poll of registered applications, although all other calls to the hub are via asynchronous XML-RPC. This use of the REST API will be remove in later releases of the widget.

Event Monitor

The current Plastic prototype work by the project is concerned with developing simple visualisation tools that can easily be hooked into the emerging VOEvent network. Here a simple client is used to take events pushed over the event network, parse, and then dispatch these events to the hub and any Plastic-aware applications running on the local machine, the monitor code formed the basis of our demonstration for the IVOA Victoria meeting.

PLASTIC Applets

We are current experimenting with John Taylor's PLASTIC Applet for data exchange.

Skeleton Client

Although not a fully functional client, the skeleton of a simple PLASTIC v0.4 application written in Perl using the PLASTIC hub's XMLRPC endpoint is shown below:

#!/usr/bin/perl

use Config::User;
use File::Spec;
use Carp;
use Data::Dumper;
use Socket;
use Net::Domain qw(hostname hostdomain);

use POSIX qw/:sys_wait_h/;
use Errno qw/EAGAIN/;

use XMLRPC::Lite;
use XMLRPC::Transport::HTTP;

# D A E M O N -------------------------------------------------------------

#my $ip = inet_ntoa(scalar(gethostbyname(hostname())));
my $ip = "localhost";
my $port = '8000';

my ( $pid, $dead );
$dead = waitpid ($pid, &WNOHANG);
#  $dead = $pid when the process dies
#  $dead = -1 if the process doesn't exist
#  $dead = 0 if the process isn't dead yet
if ( $dead != 0 ) {
    FORK: {
        if ($pid = fork) {
             print "Continuing... pid = $pid\n";
        } elsif ( defined $pid && $pid == 0 ) {
              print "Forking daemon process... pid = $pid\n";
              my $daemon;
              eval { $daemon = XMLRPC::Transport::HTTP::Daemon
               -> new (LocalPort => $port, LocalHost => $ip )
               -> dispatch_to( 'perform' );  };
              if ( $@ ) {
                 my $error = "$@";
                 croak( "Error: $error" );
              }             
     
              $url = $daemon->url();   
              print "Starting XMLRPC server at $url\n";

              eval { $daemon->handle; };  
              if ( $@ ) {
                my $error = "$@";
                croak( "Error: $error" );
              }  
  
          } elsif ($! == EAGAIN ) {
              # This is a supposedly recoverable fork error
              print "Error: recoverable fork error\n";
              sleep 5;
              redo FORK;
       } else {
              # Fall over and die screaming
              croak("Unable to fork(), this is fairly odd.");
       }
    }
}

# R P C -------------------------------------------------------------------

# Grab an RPC endpoint for the ACR
my $file = File::Spec->catfile( Config::User->Home(), ".plastic" );
croak( "Unable to open file $file" ) unless open(PREFIX, "<$file" );

my @prefix = <PREFIX>;
close( PREFIX );

my $endpoint;
foreach my $i ( 0 ... $#prefix ) {
  if ( $prefix[$i] =~ "plastic.xmlrpc.url" ) {
     my @line = split "=", $prefix[$i];
     chomp($line[1]);
     $endpoint = $line[1];
     $endpoint =~ s/\\//g;
  }    
}
print "Plastic Hub Endpoint: $endpoint\n";

my $rpc = new XMLRPC::Lite();
$rpc->proxy($endpoint);

# R E G I S T E R ----------------------------------------------------------

print "Waiting for server to start...\n";
sleep(5);

my @list;
$list[0] = 'ivo://votech.org/test/echo';
$list[1] = 'ivo://votech.org/info/getName';
$list[2] = 'ivo://votech.org/info/getIvorn';
$list[3] = 'ivo://votech.org/info/getVersion';
$list[4] = 'ivo://votech.org/info/getDescription';
$list[5] = 'ivo://votech.org/info/getIconURL';
$list[6] = 'ivo://votech.org/hub/event/ApplicationRegistered';
$list[7] = 'ivo://votech.org/hub/event/ApplicationUnregistered';
$list[8] = 'ivo://votech.org/hub/event/HubStopping';
$list[9] = 'ivo://votech.org/hub/Exception';

#my @list = ();

my $register;
eval{ $register = $rpc->call( 'plastic.hub.registerXMLRPC', 
                  'Perl Test Client', \@list, "http://$ip:$port/" ); };

if( $@ ) {
   croak( "Error: $@" );
}   

my $id;
unless( $register->fault() ) {
   $id = $register->result();
   print "Got Plastic ID of $id\n";
} else {
   croak( "Error: ". $register->faultstring );
}

# M A I N  L O O P ---------------------------------------------------------

while(1) { };

exit;

# D A E M O N   C A L L B A C K S ##########################################

sub perform {
  Plastic::perform( @_ );
}  

package Plastic;

use Data::Dumper;

sub perform {
  my @args = @_;

  print "In perform()\n";
  print Dumper( @args );
  if ($args[2] eq 'ivo://votech.org/test/echo' ) {
     return $args[3];
  }
  if ($args[2] eq 'ivo://votech.org/info/getName' ) {
     return "Perl Test Client";
  }
  if ($args[2] eq 'ivo://votech.org/info/getIvorn' ) {
     return "ivo://org.perl";
  }   
  if ($args[2] eq 'ivo://votech.org/info/getVersion' ) {
     return "0.4";
  }
  if ($args[2] eq 'ivo://votech.org/info/getDescription' ) {
     return "A simple test client written in Perl.";
  }
  if ($args[2] eq 'ivo://votech.org/info/getIconURL' ) {
     return "http://www.oreillynet.com/images/perl/sm_perl_id_313_wt.gif";
  }   
  if ($args[2] eq 'ivo://votech.org/hub/event/ApplicationRegistered' ) {
     return 1;
  }   
  if ($args[2] eq 'ivo://votech.org/hub/event/ApplicationUnregistered' ) {
     return 1;
  }   
  if ($args[2] eq 'ivo://votech.org/hub/event/HubStopping' ) {
     print "Warning: Hub Stopping Message\n";
     return 1;
  }   
  if ($args[2] eq 'ivo://votech.org/hub/Exception' ) {
     print "Warning: Hub Exception Message\n";
     print "Warning: $args[3]\n";
     return 1;
  }   

}