openhab-docs/developers/prerequisites/osgitasks.md

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

  1. Create an org.openhab.training.helloosgi bundle, 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.

  2. Create an org.openhab.training.utils bundle, which contains class TimeUtilities, that has a single method String getCurrentTimeStamp() that returns the current time stamp in format "hh:mm". Mind the TimeUtilities class might be used in some other bundles.

    Hint! Find out how can you export packages in OSGi.

  3. Create an org.openhab.training.helloosgi.modified bundle to use the TimeUtilities class to display the current time stamp on the console when it is started.

II. Services

  1. Create an org.openhab.training.electricity.provider bundle, which defines a service interface ElectricityProvider with 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;
  2. Create an org.openhab.training.electricity.homenetwork bundle:

    • with HomeElectricityNetwork implementation of the ElectricityProvider interface with infinite charge (the provide() method should always return true);
    • which registers the HomeElectricityNetwork as ElectricityProvider in the OSGi Service Registry with BundleContext.

    Hint! You can find similar tasks in the examples below.

  3. Create an org.openhab.training.electricity.consumer bundle, which contains an interface ElectricityConsumer with 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).
  4. Create an org.openhab.training.electricity.radio bundle, which:

    • implements the ElectricityConsumer interface in a BasicRadio consumer, which has specific consumption (e.g int 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 ElectricityProvider service by getting it directly from the BundleContext.

III. Service Tracker

  1. Create an org.openhab.training.electricity.battery bundle, which implements and registers Battery implementation of the ElectricityProvider service with finite charge (e.g int 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.

  2. Create an interface DynamicConsumer in an org.openhab.training.electricity.dynamicconsumer bundle that should manage the availability of the different ElectricityProvider. 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.
  3. Create a TV consumer with int consumption = 10, that implements the ElectricityConsumer interface and the DynamicConsumerinterface in an org.openhab.training.electricity.tv bundle by using ServiceTracker. The TV should be able to dynamically switch between different ElectricityProvider:

    • 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 TV should 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.util bundle in order to use ServiceTracker. Tutorials with examples can be found below.

IV. Declarative Services and Components

  1. Provider and consumer:

    • rewrite all tasks in section II. and III. to use the ElectricityProvider service 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.ds bundle in order to use Declarative Services.

  2. Create a SolarRadio consumer that extends BasicRadio from IV.1 in an org.openhab.training.electricity.solarradio bundle. This radio does not need any ElectricityProvider to 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!

  3. Create a CombinedSolarRadio that extends SolarRadio and implements DynamicConsumer in org.openhab.training.electricity.combinedradio it 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 CombinedSolarRadio stops 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 ElectricityProvider implementations and track, if the consumers are used as expected.

V. Events

  1. Create a bundle org.openhab.training.util.sender that registers as a service TimeEventSender, that sends events with topic "org/openhab/training/time" every minute with the current time stamp (hh:mm) (you can use the TimeUtilities class from chapter I.).

    Hint! Install org.eclipse.equinox.event bundle in order to use EventAdmin service for sending events.
    Hint! ScheduledExecutorService can be used in this task.

  2. Extend the org.openhab.training.electricity.tv.ds.TV class from IV.1 in an org.openhab.training.electricity.tv.events bundle to listen for events and print them on the console.

VI. Managed Services

  1. Implement the ManagedService interface in the org.openhab.training.electricity.tv.events bundle and:

    • add a configuration to the TV class 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.
  2. Create another implementation of the ElectricityProvider interface (RechargableBattery) in an org.openhab.training.electricity.rechargeablebattery bundle 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.cm bundle in order to use ConfigurationAdmin service.

  3. Create a org.openhab.training.electricity.recharger bundle 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

  1. Implement a service in the org.openhab.training.util.console bundle that adds console command, that:

    • displays all ElectricityProvider implementations 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 RechargableBattery to 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 Battery provider 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!

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}

Writing basic OSGi bundle

{:.no_toc}

Services

{:.no_toc}

Service Trackers

{:.no_toc}

Declarative Services and Components

{:.no_toc}

Managed Services

{:.no_toc}