2014-04-29

Created page with "<!-- This CSS wraps code blocks in pretty boxes --> <css> .mw-code { background-color: #fafafa; padding: 20px; border-color: #ddd; border-width: 3px; border-sty..."

New page

<!-- This CSS wraps code blocks in pretty boxes -->

<css>

.mw-code {

background-color: #fafafa;

padding: 20px;

border-color: #ddd;

border-width: 3px;

border-style: solid;

border-radius: 5px;

margin-left: 10px;

margin-right: 10px;

overflow-x: auto;

}

.mw-headline {

font-family: Helvetica Neue,Helvetica,Arial,sans-serif;

color: rgb(51, 51, 51);

}

p {

font-family: Helvetica Neue,Helvetica,Arial,sans-serif;

text-align: justify;

}

h1 {

border-bottom-color: rgb(238, 238, 238);

font-weight: bold;

padding-bottom: 17px;

font-size: 30px;

line-height: 36px;

}

h2 {

border-bottom-color: rgb(238, 238, 238);

padding-bottom: 12px;

font-weight: bold;

font-size: 24px;

line-height: 36px;

}

h3 {

border-bottom-width: 1px;

border-bottom-style: solid;

border-bottom-color: rgb(238, 238, 238);

padding-bottom: 8px;

font-size: 18px;

line-height: 27px;

}

h4 {

font-size: 14px;

}

h5 {

font-size: 12px;

}

h6 {

font-size: 11px;

color: #EBEBEB;

text-transform: uppercase;

}

a {

color: rgb(0, 105, 214);

font-family: Helvetica Neue,Helvetica,Arial,sans-serif;

}

a:visited {

color: rgb(0, 105, 214);

}

</css>

==Introduction==

This tutorial shows how OSGi Remote Services may be used with the [http://www.raspberrypi.org Raspberry Pi] or other devices. Below an entirely new service is defined, implemented, and deployed on the Raspberry Pi using ECF's implementation of [[ECF#OSGi_Remote_Services | OSGi Remote Services]].

==Define the Service==

First, it's necessary to define the new service interface. With OSGi services, this is done by creating a java interface

<source lang="java">

public interface IRaspberryPi {

/**

* Get system properties for the Raspberry Pi remote service host.

* @return Map<String,String> the system properties for the remote RP

*/

public Map<String,String> getSystemProperties();

}

</source>

This defines a very simple service to be provided by the Raspberry Pi: giving a remote consumer access to the Raspberry Pi's system properties. Other more complicated services are, of course, possible...e.g. ones that provide access to the full range of capabilities of the Raspberry Pi device.

===Asynchronous Remote Service Interface===

ECF Remote Services allows remote service consumers that ability to use Java 8's CompletableFuture to access a remote service asynchronously...i.e. without blocking in the face of network I/O. This is through an ECF Remote Services feature called [[ECF/Asynchronous_Remote_Services Asynchronous Remote | Services]]. The only thing that this requires is that an asynchronous service interface...corresponding to the synchronous service interface above, is created

<source lang="java">

public interface IRaspberryPiAsync {

/**

* Get remote system properties via CompletableFuture for non-blocking.

* Note: signature of this method is connected to {@link

* IRaspberryPi#getSystemProperties()}.

*

* @return CompletableFuture

*/

public CompletableFuture<Map<String,String>> getSystemPropertiesAsync();

}

Note the correspondence between the interface names: '''IRaspberryPi''' and '''IRaspberryPiAsync''', and the method names: '''getSystemProperties()''' and '''getSystemPropertiesAsync()'''.

These two service interfaces define the remote service. The source code for these two interfaces, all supporting OSGi meta-data are available as a complete project in the [http://git.eclipse.org/c/ecf/org.eclipse.ecf.git ECF git repo], located here: '''examples/bundles/org.eclipse.ecf.examples.raspberrypi.management'''.

==Service Host: The Remote Service Implementation==

The remote service host...in this case the Raspberry Pi device...must provide an implementation of the IRaspberryPi service interface. Here is a very simple implementation of the IRaspberryPi service interface

<source lang="java">

/**

* Implementation of IRaspberryPi service interface.

*/

public class RaspberryPi implements IRaspberryPi {

public Map<String, String> getSystemProperties() {

Properties props = System.getProperties();

Map<String, String> result = new HashMap<String,String>();

for (final String name: props.stringPropertyNames())

result.put(name, props.getProperty(name));

System.out.println("REMOTE CALL: getSystemProperties()");

return result;

}

}

</source>

==Service Host: Registering the Remote Service==

Given the OSGi Remote Services specification, and the ECF Remote Services implementation, the only other code that has to be created is the code that registers the remote service with the OSGi service registry. According to the OSGi Remote Service specification, if a service is registered with the necessary set of standardized service properties, and a compliant implementation is present in the OSGi framework, then the service will be exported for remote access.

Here is the code to set the service properties and to register the RaspberryPi service

<source lang="java">

public void start(BundleContext context) throws Exception {

Dictionary<String,Object> props = new Hashtable<String,Object>();

// Add OSGi required remote service properties

props.put("service.exported.interfaces", System.getProperty(OSGI_SERVICE_EXPORTED_INTERFACES,"*"));

// Use ECF generic server config.

props.put("service.exported.configs", "ecf.generic.server");

// Setup hostname config (default:localhost)

String hostname = System.getProperty("ecf.generic.server.hostname");

if (hostname != null)

props.put("ecf.generic.server.hostname",hostname);

// Setup port config (default:-1)

props.put("ecf.generic.server.port",new Integer(System.getProperty("ecf.generic.server.port","-1")));

// Setup IRaspberryPiAsync as async remote service

props.put("ecf.exported.async.interfaces", "*");

// This remote service registration will trigger export, and publishing via zeroconf

registration = context.registerService(IRaspberryPi.class, new RaspberryPi(), props);

System.out.println("IRaspberryPi remote service registered="+registration);

}

</source>

This block of code (in the bundle activator) is called by the OSGi framework when the enclosing bundle is started. What it's doing:

# the OSGi standard service properties are set...i.e. 'service.exported.interfaces' and 'service.exported.configs'

# some configuration-specific properties are set...i.e. 'ecf.generic.server.hostname' and 'ecf.generic.server.port'

# the ECF Asynchronous Remote Service property is set...i.e. 'ecf.exported.async.interfaces'

# the service is registered via '''context.registerService''' with the IRaspberryPi.class, a new instance of the RaspberryPi implementation class, and the previously set service props.

The source code for both the RaspberryPi implementation and the remote service registration is available in a project in the [http://git.eclipse.org/c/ecf/org.eclipse.ecf.git ECF git repo], located here: '''examples/bundles/org.eclipse.ecf.examples.raspberrypi.management.host'''.

==Raspberry Pi Prerequisites==

The main prerequisite for running our new remote service on the Raspberry Pi is the availability of a Java 8 virtual machine for the Pi. [http://www.adafruit.com/blog/2014/03/28/how-to-install-oracle-jdk-8-on-raspberry-pi-piday-raspberrypi-raspberry_pi/ here] are instructions for installing Java 8 on the Pi. Once this is done, all we need to do is create a framework that includes:

#An OSGi Framework

#A remote services implementation (ECF in this case)

#The two bundles above (i.e. 'org.eclipse.ecf.examples.raspberrypi.management' and 'org.eclipse.ecf.examples.raspberrypi.management.host')

To create this, we will use an Eclipse product config, defined as a project in the [http://git.eclipse.org/c/ecf/org.eclipse.ecf.git ECF git repo], in the following project '''examples/bundles/org.eclipse.ecf.examples.raspberrypi.management.host.feature'''. There are most certainly other ways to build and deploy this set of bundles (1-3), but this will serve for this tutorial.

When the products/RaspberryPiManagmentHost.product is exported using Eclipse, and then the output contents copied over to the Raspberry Pi, it looks like this on the RaspberryPi disk

<pre>

root@raspberrypi:/home/pi/rpi/rp2/raspberrypimgmt1# ls -A -R

.:

configuration eclipse.ini .eclipseproduct features plugins rpimgmthost.bat rpimgmthost.sh

./configuration:

config.ini

./features:

org.eclipse.ecf.examples.raspberrypi.management.host.feature_1.0.0.201404281938

./features/org.eclipse.ecf.examples.raspberrypi.management.host.feature_1.0.0.201404281938:

feature.xml

./plugins:

ch.ethz.iks.slp_1.1.0.v20140427-1612.jar

org.apache.felix.gogo.command_0.10.0.v201209301215.jar

org.apache.felix.gogo.runtime_0.10.0.v201209301036.jar

org.apache.felix.gogo.shell_0.10.0.v201212101605.jar

org.eclipse.core.jobs_3.6.0.v20140407-1602.jar

org.eclipse.ecf_3.4.0.v20140427-1612.jar

org.eclipse.ecf.console_1.0.0.v20140427-1612.jar

org.eclipse.ecf.discovery_5.0.0.v20140427-1612.jar

org.eclipse.ecf.examples.raspberrypi.management_1.0.0.201404281938.jar

org.eclipse.ecf.examples.raspberrypi.management.host_1.0.0.201404281938.jar

org.eclipse.ecf.identity_3.4.0.v20140427-1612.jar

org.eclipse.ecf.osgi.services.distribution_2.0.300.v20140427-1612.jar

org.eclipse.ecf.osgi.services.remoteserviceadmin_4.0.0.v20140427-1612.jar

org.eclipse.ecf.osgi.services.remoteserviceadmin.proxy_1.0.0.v20140427-1612.jar

org.eclipse.ecf.provider_4.5.0.v20140427-1612.jar

org.eclipse.ecf.provider.jslp_3.2.0.v20140427-1612.jar

org.eclipse.ecf.provider.remoteservice_4.1.0.v20140427-1612.jar

org.eclipse.ecf.remoteservice_8.4.100.v20140427-1612.jar

org.eclipse.ecf.remoteservice.asyncproxy_2.0.0.v20140410-1838.jar

org.eclipse.ecf.sharedobject_2.5.0.v20140427-1612.jar

org.eclipse.equinox.common_3.6.200.v20130402-1505.jar

org.eclipse.equinox.concurrent_1.1.0.v20130327-1442.jar

org.eclipse.equinox.console_1.1.0.v20140131-1639.jar

org.eclipse.equinox.event_1.3.100.v20140115-1647.jar

org.eclipse.osgi_3.10.0.v20140407-2102.jar

org.eclipse.osgi.services_3.4.0.v20140312-2051.jar

org.eclipse.osgi.services.remoteserviceadmin_1.5.100.v20140427-1612.jar

</pre>

==Service Host: Starting the Remote Service==

To start this application, register and export the RaspberryPi remote service, type

<pre>

root@raspberrypi:/home/pi/rpi/rp2/raspberrypimgmt1# sudo ./rpimgmthost.sh 192.168.1.80

</pre>

where the ip address on the LAN is given at the end (i.e. 192.168.1.80). After some time, it will produce the following output

<pre>

Hostname: 192.168.1.80

Port: 3288

javaprops=-Decf.generic.server.hostname=192.168.1.80 -Decf.generic.server.port=3288 -Declipse.ignoreApp=trueutdown=true

equinox=plugins/org.eclipse.osgi_3.10.0.v20140407-2102.jar

Debug options:

file:/home/pi/rpi/rp2/raspberrypimgmt1/.options not found

Time to load bundles: 333

IRaspberryPi remote service registered={org.eclipse.ecf.examples.raspberrypi.management.IRaspberryPi}={ecf.generic.server.port=3288, ecf.exported.async.interfaces=*, ecf.generic.server.hostname=192.168.1.80, service.exported.configs=ecf.generic.server, service.exported.interfaces=*, service.id=77, service.bundleid=28, service.scope=singleton}

osgi>

</pre>

This indicates tht the IRaspberryPi remote service has successfully been registered.

The osgi> prompt indicates that the OSGi console is available for input, allowing you to give commands to (e.g.) show the status of all the bundles in the framework:

<pre>

osgi> ss

"Framework is launched."

id State Bundle

0 ACTIVE org.eclipse.osgi_3.10.0.v20140407-2102

3 ACTIVE org.apache.felix.gogo.command_0.10.0.v201209301215

4 ACTIVE org.apache.felix.gogo.runtime_0.10.0.v201209301036

5 ACTIVE org.apache.felix.gogo.shell_0.10.0.v201212101605

6 ACTIVE org.eclipse.ecf_3.4.0.v20140427-1612

7 ACTIVE org.eclipse.ecf.console_1.0.0.v20140427-1612

8 ACTIVE org.eclipse.ecf.discovery_5.0.0.v20140427-1612

9 ACTIVE org.eclipse.ecf.identity_3.4.0.v20140427-1612

10 ACTIVE org.eclipse.ecf.osgi.services.distribution_2.0.300.v20140427-1612

11 ACTIVE org.eclipse.ecf.osgi.services.remoteserviceadmin_4.0.0.v20140427-1612

12 ACTIVE org.eclipse.ecf.osgi.services.remoteserviceadmin.proxy_1.0.0.v20140427-1612

13 ACTIVE org.eclipse.ecf.provider_4.5.0.v20140427-1612

14 ACTIVE org.eclipse.ecf.remoteservice_8.4.100.v20140427-1612

15 ACTIVE org.eclipse.ecf.remoteservice.asyncproxy_2.0.0.v20140410-1838

16 ACTIVE org.eclipse.ecf.sharedobject_2.5.0.v20140427-1612

17 ACTIVE org.eclipse.equinox.common_3.6.200.v20130402-1505

18 ACTIVE org.eclipse.equinox.concurrent_1.1.0.v20130327-1442

19 ACTIVE org.eclipse.equinox.console_1.1.0.v20140131-1639

20 ACTIVE org.eclipse.equinox.event_1.3.100.v20140115-1647

21 ACTIVE org.eclipse.core.jobs_3.6.0.v20140407-1602

22 ACTIVE org.eclipse.osgi.services_3.4.0.v20140312-2051

23 ACTIVE org.eclipse.osgi.services.remoteserviceadmin_1.5.100.v20140427-1612

24 ACTIVE org.eclipse.ecf.provider.remoteservice_4.1.0.v20140427-1612

25 ACTIVE ch.ethz.iks.slp_1.1.0.v20140427-1612

26 ACTIVE org.eclipse.ecf.provider.jslp_3.2.0.v20140427-1612

27 ACTIVE org.eclipse.ecf.examples.raspberrypi.management_1.0.0.201404281938

28 ACTIVE org.eclipse.ecf.examples.raspberrypi.management.host_1.0.0.201404281938

osgi>

</pre>

==Service Consumer: Accessing the Remote Service==

Now that the IRaspberryPi remote service is running on the Pi, we need to have some other process

Show more