The Raspberry Pi is humming, you’re logged into the Raspberry via ssh, java works,and bndtools is showing an empty workspace with only the cnf directory. In this section we will start exploring the Raspberry in the most basic way. We will create an application project that we then use to first just create a little component that plays with the hardware in a component.
In the workspace, create a project. In this tutorial this project is called osgi.enroute.examples.iot.domotica.application
, but you should obviously give it a name dear to you, just make sure it ends with .application
since the OSGi enRoute template uses that extension to provide the proper project structure for a web application. It should therefore go without saying, that you should select the OSGi enRoute template when asked.
The following code assumes the osgi.enroute.examples.iot.domotica.application
name and from this name it derives package names. If you choose your own names, make sure to proper translate these derived names.
An OSGi enRoute Application project is a full web application with REST but we are first going to ignore those goodies. As always, the easiest app is to say Hello World
(and on OSGi also Goodbye World!
). So lets create a component in the osgi.enroute.examples.iot.domotica.command
package that performs these highly complex actions:
@Component
public class DomoticaCommand {
@Activate
void activate() {
System.out.println("Hello World");
}
@Deactivate
void deactivate() {
System.out.println("Goodbye World");
}
}
Make sure you add the package to the private packages of the bundle. You can do this by double clicking on the provider.bnd
file, select the Contents
tab and drag the package in the Private Package
list.
The OSGi enRoute Application template has created a complete runnable project. The osgi.enroute.examples.iot.domotica.bndrun
file has a specification for running this application on an OSGi server that contains an HTTP server an other necessities in life. However, in this case we will use the debug.bndrun
run specification. This run specification inherits its setup from the osgi.enroute.examples.iot.domotica.bndrun
file, it just adds a number of useful debugging bundles.
The Http Server will run by (the OSGi) default on port 8080. You can change this port number by setting a run property in the osgi.enroute.examples.iot.domotica.bndrun
file:
-runproperties: org.osgi.service.http.port = 9090
So double click this file and go to the Source
tab. In the editor, add the following instruction:
-runpath: biz.aQute.remote.launcher
-runremote: \
pi; \
jdb=1044; \
host=192.168.2.4; \
shell=-1
Obviously you have to change the IP number to the one you are using. In the pre-requisites we should have started the bnd remote main program via ssh:
$ ssh pi@192.168.2.4
pi@raspberrypi ~ $ sudo bndremote -a
Listening for transport dt_socket at address: 1044
The -a
option indicates that bndremote should listen to all interfaces, not just localhost.
We now need to resolve the run specification. On the debug.bndrun
, select the Run
tab and click the Resolve
button.
The next step is to run this Run specification. Select the debug.bndrun
file and call up the context menu, and select @/Debug As/Bnd Native Launcher
. This will cause bnd to start the debugger and look for a remote agent on the specified host. If you forgot to start the remote agent then you have all the time of the world, bnd(tools) will keep tryng until it finds an agent. Once it succeeds, the ssh shell window should look like:
____________________________
Welcome to Apache Felix Gogo
g!
2015-07-14 16:41:59.701:INFO:oejs.Server:jetty-8.1.14.v20131031
2015-07-14 16:42:00.202:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080
[INFO] Started Jetty 8.1.14.v20131031 at port(s) HTTP:8080 on context path /
[INFO] Detected extended HttpService. Filters enabled.
[INFO] Http service whiteboard started
Hello world
Web server
The bndtools IDE will continuously update the bundles on the remote agent. Let’s test it by changing the “Hello World” to “I love Domotica!”.
Goodbye World!
I love Domotica
We can now run code on the Pi so the next step is to talk to do something really “Piish”. Obviously, talking to the hardware is pretty specific to the Pi. The primary library talking to the hardware in the Java world is Pi4j. We could use this library directly but we can also use the OSGi enRoute version. The OSGi enRoute distro contains a bundle osgi.enroute.iot.pi.provider
. This bundle contains Pi4j, which is a Java library based on Wiring Pi, a native code library to control the BCM2835 chip in the Raspberry Pi, which will be our gateway to leave the cyberworld and talk to things. This bundle is designed to work with the osgi.enroute.iot.circuit.provider
bundle, however, we will first descent to the Pi4J level. The osgi.enroute.iot.pi.provider
bundle therefore also registers a Pi4J GpioController.
So first add the maven dependency into the central.xml of your bnd workspace (into the cnf folder) with these lines:
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.enroute.iot.pi.provider</artifactId>
<version>2.0.0</version>
</dependency>
To see change you probably have to refresh the repository tree from eclipse repositories view. Then add osgi.enroute.iot.pi.provider
to the osgi.enroute.examples.iot.domotica.bndrun
’s -runrequires
instruction:
-runrequires: \
osgi.identity;filter:='(osgi.identity=osgi.enroute.iot.domotica.application)',\
osgi.identity;filter:='(osgi.identity=osgi.enroute.iot.pi.provider)'
Actually, the easiest way to do this is to select the Run
tab and then drag the osgi.enroute.iot.pi.provider
from the repositories to the Run Requirements list. Save this file, then go to the debug.bndrun
file and click on the Resolve
button in the Run
tab and save this file. This will load the osgi.enroute.iot.pi.provider
bundle in the Pi.
The osgi.enroute.iot.pi.provider
bundle adds a GpioController service from the Pi4j project. Since we want to use that GpioController service we need access to the type. We therefore need to add this bundle also to the bnd.bnd
file’s -buildpath
instruction.
-buildpath: \
osgi.enroute.base.api,\
osgi.enroute.logger.simple.provider,\
osgi.enroute.web.simple.provider;version=1.2,\
osgi.enroute.iot.circuit.provider,\
osgi.enroute.iot.pi.provider
You can of course also click on the +
in the bnd.bnd
’s file Build tab and it from the list.
Let’s first do something very naughty: use statics. The Pi4j library has a SystemInfo class that provides lots of information about our Pi.
@Component
public class DomoticaCommand {
@Activate
void activate() throws Exception {
System.out.println(SystemInfo.getBoardType().name()
+ " " + SystemInfo.getSerial());
}
@Deactivate
void deactivate() {
System.out.println("Goodbye World");
}
}
Save the file Java source file and watch the output:
Goodbye World!
Model2B_Rev1 00000000237a3302
It is time to get this hardware out of the static-electricy protection pouches! We are going to make an LED blink! To “design” this scenario we use a handy open source tool called “Fritzing”. It allows us to design in schema or breadboard mode. Let’s start with a schema:
.
A bit about pin numbering … that is a bit of a mess. Pi4j uses another numbering than the Raspberry connector/chip uses. This is highly confusing. In the schema we connected the LED to the Raspberry GPIO17 on in the connector pin 11, in Pi4J this called the GPIO00 pin. Confused? You will be. We will keep the Pi4J numbering as much as possible. This the connector for Pi4j numbering:
.
We connect the positive side of the LED to the GPIO 4 of the Raspberry and then connect it to ground via a 220Ω resistor. An LED is a light emitting diode, quite popular nowadays because they are very power efficient. The resistor is there to limit the current, otherwise we could destroy the Raspberry GPIO port or the LED. (Murphy says the Raspberry is the more likely candidate since it is more expensive). Remember that Electronics 101 class? We limit the current to less than (2.7V)/220Ω ~ 20 mA. This is within the Raspberry Pi limits.
We implement this schema on a breadboard. A breadboard is a little board that makes it easy to prototype with the Raspberry Pi. It provides power lines above and below the board and a prototyping area where the vertical lines are connected. The distance between the holes is standard 0.1 inch, most ICs can be delivered with pins that use this spacing. Connections are made using small wires. Our breadboard is shown in the following picture:
.
We follow industry standard colors:
A quick word about the electronics involved. LEDs are Light Emitting Diodes and the diode part is important for us – they only pass electricity one way, so we need to make sure we put them in the right way round. They have a long leg and a slightly shorter leg. The long leg goes to the plus side and the shorter leg to the negative (or 0v) side. If we’re cut the legs short (as I have done here), then another way is to look at the side of the LED – there will be a flat section. Think of the flat as a minus sign and connect that to the resistor so that it is connected to the ground side of the circuit.
You could test the circuit by connecting a temporary wire from the red 3.3V barto the LED on the side of the yellow wire. This should light the LED.
The next step is the software. The following code will start a thread and blink the LED. The details about the API are to be found at the Pi4j site. We are using the Pi4J API but realize that this API is not how you should use the Raspberry Pi on with OSGi.
private Scheduler scheduler;
private Closeable schedule;
@Activate
void activate() throws Exception {
try {
GpioController gpioController = GpioFactory.getInstance();
while (!gpioController.getProvisionedPins().isEmpty())
gpioController.unprovisionPin(gpioController.getProvisionedPins().iterator().next());
GpioPinDigitalOutput out = gpioController
.provisionDigitalOutputPin(RaspiPin.GPIO_00, "LED1",
PinState.LOW);
schedule = scheduler.schedule(() -> {
boolean high = out.getState().isHigh();
out.setState(!high);
}, 500);
} catch (Exception e) {
e.printStackTrace();
}
}
@Deactivate
void deactivate() throws IOException {
schedule.close();
System.out.println("Goodbye World!");
}
@Reference
void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
Save the code, and see how the LED is blinking at you!
We hope you’re still reading this and not escaped to the Pi4J site to see how you can use the GpioController to do more cool stuff and impress your partner with your explorations outside cyberspace. For we need to talk a bit …
Take a look at the code. This activate
method clearly shows that we have one of those evil static APIs with life cycle attitude. Static APIs with such an attitude generally spell trouble in OSGi. Things work better with services. And this is a prime example of the disadvantages. As you can see, we need this odd loop to clear out any pins that were already provisioned before. We then need to create the pin while choosing a specific GPIO. If you think about this API then you should realize that such a design does not work very well in a shared environment. What if other bundles want use a GPIO pin as well? How do we prevent it from being cleared. We picked GPIO00 but that was arbitrary, we could’ve picked any GPIO. Sadly, lots of APIs are designed with the God complex, thinking that there is a single designer that omniscient. In a modular environment we try to avoid those like the plague. So in the coming sections we show an alternative on OSGi mechanisms. This example was just to get a quick and dirty win.