16 KiB
| layout | title |
|---|---|
| developersguide | Coding tasks for OSGi |
{% include base.html %}
Coding tasks for OSGi
Introduction
OSGi coding tasks can help Java developers with no experience in OSGi and Eclipse Plug-in development to get familiar with writing bundles. This page contains tasks, related to several fundamental topics, and references to tutorials, where similar tasks are implemented.
Prerequisites
Before you start, you should first install the Eclipse IDE.
In order to run your samples in an OSGi Runtime you might want to start Equinox in a command line.
You might take a look at the Coding Guidelines as well.
Tasks
The tasks are divided in several sections:
{::options toc_levels="3"/}
- TOC {:toc}
Sample implementations are present in the openHAB docs repo.
I. Writing basic OSGi bundle
-
Create an
org.openhab.training.helloosgibundle, that prints a message on the console, when it is started and stopped. Test it in the OSGi Container.Hint! You can install a bundle in the OSGi Container with the
install {url}command.
Hint! If you still have difficulties look at the reference section. -
Create an
org.openhab.training.utilsbundle, which contains classTimeUtilities, that has a single methodString getCurrentTimeStamp()that returns the current time stamp in format "hh:mm". Mind theTimeUtilitiesclass might be used in some other bundles.Hint! Find out how can you export packages in OSGi.
-
Create an
org.openhab.training.helloosgi.modifiedbundle to use theTimeUtilitiesclass to display the current time stamp on the console when it is started.
II. Services
-
Create an
org.openhab.training.electricity.providerbundle, which defines a service interfaceElectricityProviderwith one method:boolean provide (int value)- discharges the provider with the 'value' parameter. It should return true, if the requested charge is available in the provider and false, if it is not;
-
Create an
org.openhab.training.electricity.homenetworkbundle:- with
HomeElectricityNetworkimplementation of theElectricityProviderinterface with infinite charge (theprovide()method should always return true); - which registers the
HomeElectricityNetworkasElectricityProviderin the OSGi Service Registry with BundleContext.
Hint! You can find similar tasks in the examples below.
- with
-
Create an
org.openhab.training.electricity.consumerbundle, which contains an interfaceElectricityConsumerwith methods:void startConsuming()- starts the device and displays a message on the console. If the device requires a provider (it is not energy independent), this method can set the current provider. After the device is started it should try to consume electricity equal to the device consumption from the current provider at fixed interval from 5 seconds and display a message on the console, which provider is in use at the moment;void stopConsuming()- stops the device and displays message on the console. The device should not consume electricity anymore. The device should stop, if the current provider is discharged;void setCurrentProvider(ElectricityProvider)- sets a current provider from a list with available providers;List<ElectricityProvider> getAllAvailableProviders()- returns a list with available providers (a provider is available, when it is registered in the Service Registry and has more charge, than the device consumption).
-
Create an
org.openhab.training.electricity.radiobundle, which:- implements the
ElectricityConsumerinterface in aBasicRadioconsumer, which has specific consumption (e.gint consumption = 5) and can be connected to only one provider; - the device should be able to stop automatically, when there is no provider available and display a message on the console. After that it must be started manually;
- use the
ElectricityProviderservice by getting it directly from the BundleContext.
- implements the
III. Service Tracker
-
Create an
org.openhab.training.electricity.batterybundle, which implements and registersBatteryimplementation of theElectricityProviderservice with finite charge (e.gint capacity = 20).Hint! An ElectricityProvider can be used by different consumers simultaneously. Consider whether it is necessary to make an implementation of this class thread-safe.
-
Create an interface
DynamicConsumerin anorg.openhab.training.electricity.dynamicconsumerbundle that should manage the availability of the differentElectricityProvider. It defines two methods:void providerAdded(ElectricityProvider)- called when a new provider is registered in the ServiceRegistry. It should add the provider in a list with available electricity sources for the current device;void providerRemoved(ElectricityProvider)- called when a provider is unregistered from the ServiceRegistry. It should remove the provider from a list with available electricity sources for the current device.
-
Create a
TVconsumer withint consumption = 10, that implements theElectricityConsumerinterface and theDynamicConsumerinterface in anorg.openhab.training.electricity.tvbundle by using ServiceTracker. TheTVshould be able to dynamically switch between differentElectricityProvider:- when both providers are available, it should work with the
HomeElectricityNetwork; - otherwise it should use the provider that is available at the moment;
- when no provider is available or it can not provide enough charge, the
TVshould stop; - it should be able to start automatically, if a new provider is available and is able to provide enough electricity.
Hint! Install
org.eclipse.osgi.utilbundle in order to use ServiceTracker. Tutorials with examples can be found below. - when both providers are available, it should work with the
IV. Declarative Services and Components
-
Provider and consumer:
- rewrite all tasks in section II. and III. to use the
ElectricityProviderservice by injecting it by the means of Declarative Services (do not use Service Tracker and BundleContext).The name of the new bundles will be the same, but ending with a .ds (e.g.org.openhab.training.electricity.tv.ds);
Hint! Install
org.eclipse.equinox.dsbundle in order to use Declarative Services. - rewrite all tasks in section II. and III. to use the
-
Create a
SolarRadioconsumer that extendsBasicRadiofrom IV.1 in anorg.openhab.training.electricity.solarradiobundle. This radio does not need anyElectricityProviderto run, but will use one, if it is available (the device should not stop when there are no providers available).Hint! Read about cardinality in OSGi Declarative Services!
-
Create a
CombinedSolarRadiothat extendsSolarRadioand implementsDynamicConsumerinorg.openhab.training.electricity.combinedradioit the following way:- the consumer does not need any provider to run;
- if one is available, it must set it as current and use it;
- if more than one are available, add all to the list with available providers.
Hint! What happens when you stop the provider that is not in use? Why does the
CombinedSolarRadiostops and starts? Modify the consumer to handle the removal of the service dynamically - without calling the stop and start methods every time! Read about service policy in OSGi!Hint! Test all the bundles in the OSGi container by starting and stopping the different
ElectricityProviderimplementations and track, if the consumers are used as expected.
V. Events
-
Create a bundle
org.openhab.training.util.senderthat registers as a serviceTimeEventSender, that sends events with topic "org/openhab/training/time" every minute with the current time stamp (hh:mm) (you can use theTimeUtilitiesclass from chapter I.).Hint! Install
org.eclipse.equinox.eventbundle in order to use EventAdmin service for sending events.
Hint! ScheduledExecutorService can be used in this task. -
Extend the
org.openhab.training.electricity.tv.ds.TVclass from IV.1 in anorg.openhab.training.electricity.tv.eventsbundle to listen for events and print them on the console.
VI. Managed Services
-
Implement the ManagedService interface in the
org.openhab.training.electricity.tv.eventsbundle and:- add a configuration to the
TVclass with property "autoSleep" and value a timestamp (hh:mm); - modify the method that listens for events with topic "time" to stop the bundle, when the "autoSleep" property is equal to the "time" topic.
- add a configuration to the
-
Create another implementation of the
ElectricityProviderinterface (RechargableBattery) in anorg.openhab.training.electricity.rechargeablebatterybundle that:- has a finite charge (e.g
int capacity = 30); - implements the ManagedService interface. After this modification, it should be possible to change the charge of a battery with a
setCharge(int capacity)method;
Hint! Read about the ConfigurationAdmin service and how you can use it to change the configuration of a ManagedService. You might want to implement additional bundle that is using the ConfigurationAdmin service to change the configuration of the battery to perform a quick test.
Hint! Install
org.eclipse.equinox.cmbundle in order to use ConfigurationAdmin service. - has a finite charge (e.g
-
Create a
org.openhab.training.electricity.rechargerbundle that will wait 10 seconds after it is activated and will recharge a rechargeable battery if it is registered as a service.
VII. Console Commands
-
Implement a service in the
org.openhab.training.util.consolebundle that adds console command, that:- displays all
ElectricityProviderimplementations that are registered with their charge; - displays all consumers, to which providers are they connected (which providers are available) and what is the current provider at the moment;
Hint! You might have to register all consumers as services in the OSGi ServiceRegistry.
- sets the charge of the
RechargableBatteryto a provided value; - changes the configuration of the
TV.
Hint! You can add console commands with the help of CommandProvider
Hint! Test the console commands in the OSGi runtime by starting the different Radio consumers and the TV consumer. Start only the
Batteryprovider and wait until it is discharged. Check if the consumers have stopped as expected. Recharge the battery and check, if the consumers have started. You can try out different scenarios as well! - displays all
References
Some of the tutorials listed below are not up-to-date with the latest versions of the Equinox framework or are written to be run in another implementation of the OSGi Runtime (e.g. Apache Felix). They can help you with solving the tasks above. This resources are divided in several groups.
Multiple topics
{:.no_toc}
- This tutorials simply cover more than one from the topics below:
Writing basic OSGi bundle
{:.no_toc}
- This tutorials are focused on writing basic bundle, managing the dependencies between the bundles and running them in an OSGi container:
Services
{:.no_toc}
- Registering and using Services with the low-level OSGi API:
- Getting started with OSGi: Registering a Service;
- Getting started with OSGi: Consuming a Service;
- Apache Felix Tutorial: A bundle that listens for OSGi service events;
- Apache Felix Tutorial: A bundle that implements a dictionary service;
- Apache Felix Tutorial: A bundle that implements another dictionary service;
- Apache Felix Tutorial: A bundle that implements a simple dictionary service client;
- Apache Felix Tutorial: A bundle that implements a more robust dictionary service client.
Service Trackers
{:.no_toc}
- OSGi Service Tracker simplifies using services from the Framework's registry. You can find example usage in the links below:
- Getting started with OSGi: Dynamic Service Tracking;
- Apache Felix Tutorial: A bundle that implements a dictionary service client using the Service Tracker;
- Apache Felix Tutorial: A bundle that implements a spell checker service using dictionary services.;
- Apache Felix Tutorial: A bundle that implements a spell checker service client;
- OSGi - ServiceTracker - ServiceTrackerCustomizer.
Declarative Services and Components
{:.no_toc}
- OSGi Declarative Services is a high level API for managing services in OSGi. Its functionality is widely used in the openHAB project. Tutorials about the topic:
Managed Services
{:.no_toc}