Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Tutorial: ECF Remote Services for Raspberry Pi GPIO"

(GPIO Pins)
Line 87: Line 87:
 
==GPIO Pins==
 
==GPIO Pins==
  
Each GPIO digital pins have two modes:  output and input.  For output, each pin can be in either the 'HIGH' state, or the 'LOW' state, and the control of the pin state is what we would like to manipulate to give our application runtime behavior.  After connecting a single LED to the Raspberry Pi GPIO, changing the output on a given pin to HIGH will turn the LED on, while setting to low will turn it off.  See [https://projects.drogon.net/raspberry-pi/gpio-examples/tux-crossing/gpio-examples-1-a-single-led/ this example] for a description of how to connected a single LED to the Raspberry Pi GPIO.   
+
Each GPIO digital pins have two modes:  output and input.  For output, each pin can be in either the 'HIGH' state, or the 'LOW' state, and the control of the pin state is what we would like to manipulate to give our application runtime behavior.  After connecting a single LED to the Raspberry Pi GPIO, changing the output on a given pin to HIGH will turn the LED on, while setting to low will turn it off.  See [https://projects.drogon.net/raspberry-pi/gpio-examples/tux-crossing/gpio-examples-1-a-single-led/ these instructions] for how to physically connect a single LED to the Raspberry Pi GPIO.   
  
Below is a picture of a Raspberry Pi with an LED connected to GPIO digital output pin 0, as per the [https://projects.drogon.net/raspberry-pi/gpio-examples/tux-crossing/gpio-examples-1-a-single-led/ instructions here].  This is the GPIO setup used to demonstrate the remote services described below.
+
Below is a picture of my Raspberry Pi with an LED connected to GPIO digital output pin 0, as per the [https://projects.drogon.net/raspberry-pi/gpio-examples/tux-crossing/gpio-examples-1-a-single-led/ these instructions].   
  
 
[[File:Ledsetup.png]]
 
[[File:Ledsetup.png]]
Line 107: Line 107:
 
</source>
 
</source>
  
For this tutorial, we will be interested only in the '''getState''' and '''setState''' methods from this service interface.  Note that at runtime we may create as many instances of this service interface as desired.  Current Raspberry Pi's have two rows of 10 pins for a total of 20 physical GPIO pins.    To control our LED, we only need to control a single pin, so will only need a single instance of the IGPIOPinOutput service.
+
For this tutorial, we will be interested only in the '''getState''' and '''setState''' methods from this service interface.  Note that at runtime we may create as many instances of this service interface as desired.  Modern Raspberry Pi's have two rows of 10 pins for a total of 20 physical GPIO pins.    To control our LED, we only need to control a single pin, so will only need a single instance of the IGPIOPinOutput service that communicates with pin id=0.
  
To find and use an instance of IGPIOPinOutput we can use one of several OSGi mechanisms:  1) Declarative Services; 2) ServiceTracker; 3) BundleContext.  For this tutorial, we will use a very simple ServiceTracker.  The full code for this example can be located in the start method of [https://github.com/ECF/RaspberryPI/blob/master/test/bundles/org.eclipse.ecf.raspberrypi.test.gpio/src/org/eclipse/ecf/raspberrypi/test/gpio/Activator.java this test code].  The important fragments from this example are the implementation of the '''addingService''' method, which is executed when instances of IGPIOPinOutput are registered in the OSGi service registry
+
To find and call methods on an active instance of the IGPIOPinOutput service there are several mechanisms available (e.g. Declarative Services, Blueprint, Spring, ServiceTracker, ServiceReferences, etc.).  For this tutorial, we will use a very simple ServiceTracker.  The complete code for this example can be located in the start method of [https://github.com/ECF/RaspberryPI/blob/master/test/bundles/org.eclipse.ecf.raspberrypi.test.gpio/src/org/eclipse/ecf/raspberrypi/test/gpio/Activator.java this test code].  The important fragments is the implementation of the '''addingService''' method, which is called automatically when instances of IGPIOPinOutput are registered:
  
 
<source lang="java">
 
<source lang="java">
 
public IGPIOPinOutput addingService(ServiceReference<IGPIOPinOutput> reference) {
 
public IGPIOPinOutput addingService(ServiceReference<IGPIOPinOutput> reference) {
     System.out.println("Adding GPIO Pin Output service.   id="+reference.getProperty(IGPIOPinOutput.PIN_ID_PROP));
+
     ....
 +
    // Get the service instance
 
     IGPIOPinOutput pin = context.getService(reference);
 
     IGPIOPinOutput pin = context.getService(reference);
 +
    // Print out info about it's current state
 
     System.out.println("  current pin state is "+(pin.getState()?"HIGH":"LOW"));
 
     System.out.println("  current pin state is "+(pin.getState()?"HIGH":"LOW"));
 
     System.out.println("  setting state to HIGH");
 
     System.out.println("  setting state to HIGH");
 +
    // Set the pin's state to true/HIGH
 
     pin.setState(true);
 
     pin.setState(true);
 
     return pin;
 
     return pin;
Line 122: Line 125:
 
</source>
 
</source>
  
Note that when the IGPIOPinService is added, the service.setState(true) method is called, which will set the state of the pin to HIGH, turning on the LED connected to that pin.
+
Note that when a IGPIOPinService is added, the service.setState(true) method is called, setting the state of the pin to HIGH, and turning on/lighting the LED connected to that pin.     
 
+
When this test code is run on a Raspberry Pi, this appears on the OSGi console:
As well, we will implement '''removedService''' which is executed when instances of IGPIOPinOutput are unregistered.
+
 
+
<source lang="java">
+
public void removedService(ServiceReference<IGPIOPinOutput> reference,
+
                          IGPIOPinOutput service) {
+
     System.out.println("Removing GPIO Pin service. id="+reference.getProperty(IGPIOPinOutput.PIN_ID_PROP));
+
    System.out.println("  setting state to LOW");
+
    service.setState(false);
+
}
+
</source>
+
 
+
When the service is removed, the service.setState(false) is called, which will set the state of pin 0 to LOW, turning off the LED connected to that pin.
+
 
+
When this test bundle is run on a Raspberry Pi (using Java8+Equinox 4.4), this appears on the OSGi console:
+
  
 
<pre>
 
<pre>
Line 146: Line 135:
 
</pre>
 
</pre>
  
the LED lights up
+
and as a result of the call to '''pin.setState(true)''' the LED connected to GPIO pin 0 lights up
  
 
[[File:Ledhigh.png]]
 
[[File:Ledhigh.png]]
  
If we then stop this test bundle, this appears on the OSGi console
+
Here is a [https://www.youtube.com/watch?v=BtS_JDyiKkU&feature=youtu.be short video showing the running of this test] code.  Thanks to ECF committer Wim Jongman for creating the video and making it available.
  
<pre>
+
==Exporting the GPIO Pin Output Service ==
osgi> stop 3
+
 
Removing GPIO Pin service. id=0
+
To make the control of GPIO pin 0 available for remote access, with ECF Remote Services all we need to do is to provide values for some standardized service properties when registering the IGPIOPinOutput instance.  The names and appropriate types/values of these service properties are standardized by OSGi Remote Services, which is specified by [http://www.osgi.org/Specifications/HomePage OSGi Enterprise specification].
   setting state to LOW
+
 
</pre>
+
Here is the code to register and export the IGPIOPinOutput service
 +
 
 +
<source lang="java">
 +
Map<String, Object> pinProps = new HashMap<String, Object>();
 +
pinProps.put("service.exported.interfaces", "*");
 +
pinProps.put("service.exported.configs", "ecf.generic.server");
 +
pinProps.put("ecf.generic.server.port", "3288");
 +
pinProps.put("ecf.generic.server.hostname",InetAddress.getLocalHost().getHostAddress());
 +
pinProps.put("ecf.exported.async.interfaces", "*");
 +
...
 +
 
 +
// register and export GPIOPin 0
 +
reg = Pi4jGPIOPinOutput.registerGPIOPinOutput(0, pinProps, context);
 +
</source>
 +
 
 +
See [https://github.com/ECF/RaspberryPI/blob/master/test/bundles/org.eclipse.ecf.raspberrypi.test.gpio/src/org/eclipse/ecf/raspberrypi/test/gpio/Activator.java here for the entire source for this example].
 +
 
 +
With ECF's Remote Services implementation present, the properties added above will result in the IGPIOPinOutput service being exported as a remote service.  The export happens automatically during the registration of the IGPIOPinOutput service (inside the registerGPIOPinOutput method in the above code).  With the default discovery policy, exporting this remote service will also advertise/publish it for network-based discovery.  For this [https://github.com/ECF/RaspberryPI/tree/master/test/features/org.eclipse.ecf.raspberrypi.test.gpio.feature example], we use the SLP protocol (RFC 2608) for LAN-based network discovery.  ECF Remote Services provides [https://wiki.eclipse.org/ECF#Customization_of_ECF_Remote_Services_.28new_Discovery_and.2For_Distribution_providers.29 multiple alternatives for discovery], with support for both networked an non-network discovery alternatives.
 +
 
 +
==Discovering the IGPIOPinOutput Service==
 +
 
 +
Once exported, remote consumers (clients) may discover and then call methods on the IGPIOPinOutput remote service.  To demonstrate this, here is a simple Eclipse-based user interface to present the discovered IGPIOPinOutput remote service instances.  The code for this Eclipse view is [https://github.com/ECF/RaspberryPI/tree/master/test/bundles/org.eclipse.ecf.raspberrypi.test.gpio.ide in the test/bundles/org.eclipse.ecf.raspberrypi.test.gpio.ide] project.   When run in the Eclipse ide, the empty view (no discovered IGPIOPinOutput services) looks like this
 +
 
 +
[[File:eclipsenopins.png]]
 +
 
 +
After discovering an instance of IGPIOPinOutput remote service via SLP LAN-based discovery the view is automatically updated with the IGPIOPinOutput proxy, which is automatically created by the OSGi Remote Services implementation.
 +
 
 +
[[File:eclipsepinlow.png]]
 +
 
 +
With the discovery of this IGPIOPinOutput remote service, and it's appearance in this view, a simple click on the 'State (click to toggle)' cell results in the pin toggling it's state via a call to IGPIOPinUpdate.setState, resulting in both the Eclipse UI being updated with a different icon
 +
 
 +
[[File:eclipsepinhigh.png]]
 +
 
 +
and the LED that's connected to the Raspberry Pi lights up
 +
 
 +
[[File:leghigheclipse.png]]
 +
 
 +
The same as if we had accessed the IGPIOPinOutput service from the Raspberry Pi directly. 
 +
 
 +
==Technical Notes==
 +
 
 +
OSGi Remote Services allows service consumers to ignore the underlying communications transport used for the remoting of the IGPIOPinOutput service.  The code implementing the Eclipse view does not access *any* transport-specific mechanisms, allowing both the Raspberry Pi (service host) and the Eclipse view to use whatever provider transport they prefer.
 +
 
 +
The dynamics of unreliable remote services (i.e. that services come and go over time) is handled extremely well by OSGi services.
 +
 
 +
ECF provides support for using the [[ECF/Asynchronous_Remote_Services | Java8 CompletableFuture for asynchronous remote services]], eliminating the potential for user interface blocking, without complicated threading code.  On the remote service consumer (Eclipse UI in this case), the ECF proxy  automatically implements this asynchronous service type
 +
 
 +
 
 +
<source lang="java">
 +
package org.eclipse.ecf.raspberrypi.gpio;
 +
 
 +
import java.util.concurrent.CompletableFuture;
 +
 
 +
public interface IGPIOPinOutputAsync {
 +
 
 +
public CompletableFuture<Boolean> getStateAsync();
 +
 
 +
public CompletableFuture<Void> setStateAsync(boolean value);
 +
...
 +
 
 +
}
 +
</source>
 +
 
 +
The full source for this asynchronous service interface is available [https://github.com/ECF/RaspberryPI/blob/master/bundles/org.eclipse.ecf.raspberrypi.gpio/src/org/eclipse/ecf/raspberrypi/gpio/IGPIOPinOutputAsync.java here].
 +
 
 +
The Eclipse UI code can then use this asynchronous service to remotely control the GPIO Pin 0 without any blocking operations.  The implementation of the IGPIOPinOutputAsync interface is created on the Eclipse client/consumer by the ECF Remote Services proxy creation. 
 +
 
 +
Here is a snippet from the implementation of the GPIO Pin View class, showing the use of the IGPIOPinOutputAsync  and support for lambda expressions
 +
 
 +
<source lang="java">
 +
public void toggle() {
 +
// Set waiting to true
 +
waiting = true;
 +
boolean newState = !this.state;
 +
// If we have asynchronous access to service,
 +
// then use it
 +
if (pinOutputAsync != null) {
 +
// Set state asynchronously to newState,
 +
// and when complete change the UI state
 +
// and refresh the viewer
 +
pinOutputAsync.setStateAsync(newState).whenComplete(
 +
(result, exception) -> {
 +
this.waiting = false;
 +
if (viewer != null) {
 +
// No exception means success
 +
if (exception == null) {
 +
// Set UI state to newState
 +
state = newState;
 +
asyncRefresh();
 +
} else
 +
showCommErrorDialog(exception);
 +
}
 +
});
 +
} else {
 +
// If we do not have access to async service, then
 +
// call pinOutput synchronously
 +
pinOutput.setState(newState);
 +
state = newState;
 +
}
 +
}
 +
</source>
 +
 
 +
The entire source for this view class is available [https://github.com/ECF/RaspberryPI/blob/master/test/bundles/org.eclipse.ecf.raspberrypi.test.gpio.ide/src/org/eclipse/ecf/raspberrypi/internal/test/gpio/ide/views/RpiGPIOPinView.java here].
 +
 
 +
More about asynchronous remote services is described in [[ECF/Asynchronous_Remote_Services | Asynchronous Remote Services]].
 +
 
 +
==Related Articles==
 +
 
 +
[[Tutorial:_Raspberry_Pi_GPIO_with_OSGi_Services | Tutorial:Raspberry Pi GPIO with OSGi Services]]
 +
 
 +
[[ECF/Asynchronous_Remote_Services | Asynchronous Remote Services]]
 +
 
 +
[[Getting Started with ECF's OSGi Remote Services Implementation]]
  
and the LED goes out.
+
[[EIG:Download|Download ECF Remote Services/RSA Implementation]]
  
Here is a [https://www.youtube.com/watch?v=BtS_JDyiKkU&feature=youtu.be short video showing the running of this test] code by using the Apache Webconsole.  Thanks to ECF committer Wim Jongman for creating the video.
+
[[EIG:Add to Target Platform|How to Add Remote Services/RSA to Your Target Platform]]
  
 
==GPIO Input==
 
==GPIO Input==

Revision as of 14:16, 22 October 2014


Introduction

This article demonstrates how to use Remote Services to interact with networked devices based upon Raspberry Pi GPIO. The use of Remote Services provides clear advantages:

  1. The Service Interface provides a simple, clear, and flexible abstraction for accessing individual GPIO pins. This enables system-wide loose coupling and high cohesion, two desirable design characteristics for networked systems.
  2. There are multiple technical advantages from using Remote Services
    1. Dynamics - Hardware-based services come and go (especially when made available via a network), and applications can be notified and adjust appropriately
    2. Service Versioning - Hardware capabilities and their associated services evolve over time, and this can require versioning the Service Interface
    3. Support for Multiple Injection Frameworks - Declarative Services, Blueprint, Spring, and others can be used as desired
    4. Support for Service-Level Security - Flexible policies to control, restrict, and/or manage services may be defined as appropriate for the application
    5. Standardized and Extensible Network Distribution and Discovery - ECF Remote Services provides full interoperability through open standards, as well as exposing full access to open, extensible, community-developed APIs

In this article, we step through the declaration, implementation, and testing of services for controlling individual GPIO Pins. After showing how these services can be used to control a simple light application, we then describe how to use ECF Remote Services to distribute these services across a network. We then demonstrate how these GPIO pin services can be easily used by an Eclipse-based user interface to remotely control the state of individual GPIO Pins.

GPIO Pins

Each GPIO digital pins have two modes: output and input. For output, each pin can be in either the 'HIGH' state, or the 'LOW' state, and the control of the pin state is what we would like to manipulate to give our application runtime behavior. After connecting a single LED to the Raspberry Pi GPIO, changing the output on a given pin to HIGH will turn the LED on, while setting to low will turn it off. See these instructions for how to physically connect a single LED to the Raspberry Pi GPIO.

Below is a picture of my Raspberry Pi with an LED connected to GPIO digital output pin 0, as per the these instructions.

Ledsetup.png

We start by declaring a GPIO pin output service interface. This service interface declares methods for getting and setting the state of a single GPIO pin. Here is the IGPIOPinOutput service interface:

public interface IGPIOPinOutput extends IGPIOPin {
 
	public boolean getState();
 
	public void setState(boolean value);
 
...
 
}

For this tutorial, we will be interested only in the getState and setState methods from this service interface. Note that at runtime we may create as many instances of this service interface as desired. Modern Raspberry Pi's have two rows of 10 pins for a total of 20 physical GPIO pins. To control our LED, we only need to control a single pin, so will only need a single instance of the IGPIOPinOutput service that communicates with pin id=0.

To find and call methods on an active instance of the IGPIOPinOutput service there are several mechanisms available (e.g. Declarative Services, Blueprint, Spring, ServiceTracker, ServiceReferences, etc.). For this tutorial, we will use a very simple ServiceTracker. The complete code for this example can be located in the start method of this test code. The important fragments is the implementation of the addingService method, which is called automatically when instances of IGPIOPinOutput are registered:

public IGPIOPinOutput addingService(ServiceReference<IGPIOPinOutput> reference) {
    ....
    // Get the service instance
    IGPIOPinOutput pin = context.getService(reference);
    // Print out info about it's current state
    System.out.println("  current pin state is "+(pin.getState()?"HIGH":"LOW"));
    System.out.println("  setting state to HIGH");
    // Set the pin's state to true/HIGH
    pin.setState(true);
    return pin;
}

Note that when a IGPIOPinService is added, the service.setState(true) method is called, setting the state of the pin to HIGH, and turning on/lighting the LED connected to that pin. When this test code is run on a Raspberry Pi, this appears on the OSGi console:

osgi> start 3
Adding GPIO Pin Output service.   id=0
  current pin state is LOW
  setting state to HIGH

and as a result of the call to pin.setState(true) the LED connected to GPIO pin 0 lights up

Ledhigh.png

Here is a short video showing the running of this test code. Thanks to ECF committer Wim Jongman for creating the video and making it available.

Exporting the GPIO Pin Output Service

To make the control of GPIO pin 0 available for remote access, with ECF Remote Services all we need to do is to provide values for some standardized service properties when registering the IGPIOPinOutput instance. The names and appropriate types/values of these service properties are standardized by OSGi Remote Services, which is specified by OSGi Enterprise specification.

Here is the code to register and export the IGPIOPinOutput service

Map<String, Object> pinProps = new HashMap<String, Object>();
pinProps.put("service.exported.interfaces", "*");
pinProps.put("service.exported.configs", "ecf.generic.server");
pinProps.put("ecf.generic.server.port", "3288");
pinProps.put("ecf.generic.server.hostname",InetAddress.getLocalHost().getHostAddress());
pinProps.put("ecf.exported.async.interfaces", "*");
...
 
// register and export GPIOPin 0
reg = Pi4jGPIOPinOutput.registerGPIOPinOutput(0, pinProps, context);

See here for the entire source for this example.

With ECF's Remote Services implementation present, the properties added above will result in the IGPIOPinOutput service being exported as a remote service. The export happens automatically during the registration of the IGPIOPinOutput service (inside the registerGPIOPinOutput method in the above code). With the default discovery policy, exporting this remote service will also advertise/publish it for network-based discovery. For this example, we use the SLP protocol (RFC 2608) for LAN-based network discovery. ECF Remote Services provides multiple alternatives for discovery, with support for both networked an non-network discovery alternatives.

Discovering the IGPIOPinOutput Service

Once exported, remote consumers (clients) may discover and then call methods on the IGPIOPinOutput remote service. To demonstrate this, here is a simple Eclipse-based user interface to present the discovered IGPIOPinOutput remote service instances. The code for this Eclipse view is in the test/bundles/org.eclipse.ecf.raspberrypi.test.gpio.ide project. When run in the Eclipse ide, the empty view (no discovered IGPIOPinOutput services) looks like this

Eclipsenopins.png

After discovering an instance of IGPIOPinOutput remote service via SLP LAN-based discovery the view is automatically updated with the IGPIOPinOutput proxy, which is automatically created by the OSGi Remote Services implementation.

Eclipsepinlow.png

With the discovery of this IGPIOPinOutput remote service, and it's appearance in this view, a simple click on the 'State (click to toggle)' cell results in the pin toggling it's state via a call to IGPIOPinUpdate.setState, resulting in both the Eclipse UI being updated with a different icon

Eclipsepinhigh.png

and the LED that's connected to the Raspberry Pi lights up

Leghigheclipse.png

The same as if we had accessed the IGPIOPinOutput service from the Raspberry Pi directly.

Technical Notes

OSGi Remote Services allows service consumers to ignore the underlying communications transport used for the remoting of the IGPIOPinOutput service. The code implementing the Eclipse view does not access *any* transport-specific mechanisms, allowing both the Raspberry Pi (service host) and the Eclipse view to use whatever provider transport they prefer.

The dynamics of unreliable remote services (i.e. that services come and go over time) is handled extremely well by OSGi services.

ECF provides support for using the Java8 CompletableFuture for asynchronous remote services, eliminating the potential for user interface blocking, without complicated threading code. On the remote service consumer (Eclipse UI in this case), the ECF proxy automatically implements this asynchronous service type


package org.eclipse.ecf.raspberrypi.gpio;
 
import java.util.concurrent.CompletableFuture;
 
public interface IGPIOPinOutputAsync {
 
	public CompletableFuture<Boolean> getStateAsync();
 
	public CompletableFuture<Void> setStateAsync(boolean value);
...
 
}

The full source for this asynchronous service interface is available here.

The Eclipse UI code can then use this asynchronous service to remotely control the GPIO Pin 0 without any blocking operations. The implementation of the IGPIOPinOutputAsync interface is created on the Eclipse client/consumer by the ECF Remote Services proxy creation.

Here is a snippet from the implementation of the GPIO Pin View class, showing the use of the IGPIOPinOutputAsync and support for lambda expressions

public void toggle() {
	// Set waiting to true
	waiting = true;
	boolean newState = !this.state;
	// If we have asynchronous access to service,
	// then use it
	if (pinOutputAsync != null) {
		// Set state asynchronously to newState,
		// and when complete change the UI state
		// and refresh the viewer
		pinOutputAsync.setStateAsync(newState).whenComplete(
				(result, exception) -> {
					this.waiting = false;
					if (viewer != null) {
						// No exception means success
						if (exception == null) {
							// Set UI state to newState
							state = newState;
							asyncRefresh();
						} else
							showCommErrorDialog(exception);
					}
				});
	} else {
		// If we do not have access to async service, then
		// call pinOutput synchronously
		pinOutput.setState(newState);
		state = newState;
	}
}

The entire source for this view class is available here.

More about asynchronous remote services is described in Asynchronous Remote Services.

Related Articles

Tutorial:Raspberry Pi GPIO with OSGi Services

Asynchronous Remote Services

Getting Started with ECF's OSGi Remote Services Implementation

Download ECF Remote Services/RSA Implementation

How to Add Remote Services/RSA to Your Target Platform

GPIO Input

In addition to controlling devices that are connected to one or more GPIO pins, it's also possible to receive asynchronous notifications of inputs to digital pins. To do this with OSGi services we will use a very useful OSGi service pattern called the whiteboard pattern. The whiteboard pattern is described in links given under Related Articles below.

For the whiteboard pattern we need another service interface, called IGPIOPinInputListener

public interface IGPIOPinInputListener {
 
	void handleInputEvent(GPIOPinInputEvent event);
 
}

and the associated GPIOPinInputEvent

public class GPIOPinInputEvent extends AbstractGPIOPinEvent implements
		Serializable {
 
	private static final long serialVersionUID = -6103636181685626657L;
 
	private final boolean state;
 
	public GPIOPinInputEvent(int pinId, boolean state) {
		super(pinId);
		this.state = state;
	}
 
	public boolean getState() {
		return state;
	}
 
	@Override
	public String toString() {
		return "GPIOPinInputEvent [getPinId()=" + getPinId() + ", state="
				+ state + "]";
	}
 
}

With the whiteboard pattern, instead of clients looking up/retrieving services (as with IGPIOPinOutput and the ServiceTracker given above), what's necessary is that the IGPIOPinInputListener be implemented and then an instance registered in the OSGi Service registry. For example, here's a very simple class that implements IGPIOPinInputListener

class TestGPIOPinInputListener implements IGPIOPinInputListener {
    @Override
    public void handleInputEvent(GPIOPinInputEvent event) {
        System.out.println("TestGPIOPinInputListener.handleInputEvent(event="+event+")");
    }
}

and then we create an instance of this class, create some service properties and register this instance via the OSGi BundleContext (context):

// Create properties
Hashtable props = IGPIOPin.Util.createInputListenerProps(IGPIOPin.DEFAULT_INPUT_PIN);
// Create and register listener using context and props created above
context.registerService(IGPIOPinInputListener.class, new TestGPIOPinInputListener(), props);

This listener is then notified and produces output when the DEFAULT_INPUT_PIN changes it's state:

TestGPIOPinInputListener.handleInputEvent(event=GPIOPinInputEvent [getPinId()=2, state=false])

All of the code above is provided in the ECF RaspberryPi github repository. The service interfaces above (IGPIOPinOutput and IGPIOPinInputListener and event classes) are available in the bundles/org.eclipse.ecf.raspberrypi.gpio project.

Also available is a complete working implementation of this service API based upon/using Pi4j. This implementation is in the bundles/org.eclipse.ecf.raspberrypi.gpio.pi4j project.

The GPIO input and output test code is available in a test bundle test/bundles/org.eclipse.ecf.raspberrypi.test.gpio. This bundle has a single Activator class. Also available is a PDE feature and product configuration, along with a built version ready to run on a working Raspberry Pi with Java8 installed in test/features/org.eclipse.ecf.raspberrypi.test.gpio/build/raspberrypitestgpio.zip.

Remote Control for GPIO Pins

See the OSGi Remote Services for Raspberry Pi GPIO tutorial.

Related Articles

Listeners Considered Harmful: The 'Whiteboard Pattern'

The whiteboard model

OSGi Remote Services for Raspberry Pi GPIO

Getting Started with ECF's OSGi Remote Services Implementation

Download ECF Remote Services/RSA Implementation

How to Add Remote Services/RSA to Your Target Platform

Back to the top