Jini-Kamera 1.0
Steuerung einer Fotokamera
mit Java und Jini
Notizen zu einer
Designstudie
Inhaltsverzeichnis
1. Änderungshistorie *
2. Einführung *
3. Zielsetzung *
4. Die Beispielimplementierung *
4.1. Motivation *
4.2. Beteiligte Komponenten *
4.2.1. Jini-Kamera
*4.2.2. Jini-Drucker
*4.2.3. Jini-Controller
*4.3. Realisierte Dienste *
4.3.1. Allgemeines
*4.3.2. Die Interfaces
*4.3.3. KameraDienst
*4.3.4. DruckDienst
*4.3.5. BetrachterDienst
*4.4. Bedienung *
4.4.1. Starten der Komponenten
*4.4.2. Aufrufen der Dienste
*5. Technische Details *
5.1. Die Kameraansteuerung *
5.2. Jini-Dienst als RMI-Client *
5.3. RMI-Server als Jini-Dienst *
5.4. Einfaches Objekt als Jini-Dienst *
5.5. Automatisches Starten der Komponenten *
5.6. Finden eines LookupServers *
5.7. Finden und Aufrufen der Dienste *
6. Hinweis auf weitere Dokumente *
[...]
18.09.2002 - gekürzte Version für Veröffentlichung
Auf eine detaillierte Erläuterung von Java und Jini wird hier verzichtet. Zu diesem Zweck sei auf auf den Artikel "Jini, die Erste – Kamera läuft!" von Herbert Bader und Roland Schubert in JavaSpektrum 5/1999 und das dort aufgeführte Literaturverzeichnis verwiesen.
Ein paar Anmerkungen dennoch vorweg:
"Java" bezeichnet einerseits die von Sun Microsystems entwickelte Programmiersprache. Andererseits gibt es von Sun eine Java-Plattform (derzeit in Version 2.0), die als "Java Runtime Environment" (JRE) einen Byte-Code-Interpreter ("Java-Virtual-Machine", JVM) und die nötigen Klassenbibliotheken enthält, um in Byte-Code übersetzte Java Programme auszuführen. Außerdem gibt es von Sun ein "Java Development Kit" (JDK) mit Compiler, Debugger und weiteren Entwicklungswerkzeugen. Auch von anderen Firmen gibt es Entwicklungsumgebungen für Java. Die Kontrolle über die Java-Plattform möchte Sun weiterhin für sich beanspruchen und auf diese Weise sicherstellen, daß Java-Programme tatsächlich unabhänging von Hardware und Betriebssystem auf der Java-Plattform lauffähig sind.
Jini – ebenfalls von Sun, verfügbar seit Januar 1999 stellt eine Sammlung von Klassen dar, mit deren Hilfe eine leichte Implementierung von verteilten Applikationen ermöglicht werden soll. Dies umfaßt insbesondere Mechanismen, die die grundsätzliche Problematik von verteilten Systemen betreffen, nämlich Synchronisation der Komponenten sowie temporärer Ausfall von Komponenten bzw. die dynamische Netzstruktur im allgemeinen.
Fakt bleibt: Auch mit Jini bleibt dem Entwickler eine möglichst präzise Einschätzung der zukünftigen Verwendung seiner Applikation nicht erspart, um das Design entsprechend anzupassen. Eine Vorhersage von Netz- oder Serverbelastung sowie Ausfallzeiten kann auch Jini nicht leisten. Es besteht aber die Chance, mit Jini eine einfache Handhabung weitverbreiteter Standardfälle zu finden. Auch für komplexe Anwendungen ist Jini flexibel einzusetzen.
Im Rahmen des Projektes "Jini-Kamera" wurde untersucht, inwieweit die neue Technologie unter Einbeziehung von Hardware (z.B. einer Kamera) tatsächlich eingesetzt werden kann. Es wurden etliche Varianten diskutiert (siehe auch Kap 6) , von denen die unten beschriebene Beispielimplementierung ausgeführt wurde.
Die übrigen Varianten schieden meist aus Gründen des Aufwandes aus. Das ursprünglich avisierte "Jini-Kästchen" mußte mangels Verfügbarkeit einer geeigneten Jini-Plattform für Embedded-Systeme ebenfalls zurückgestellt werden.
Ausgangspunkt war das auch von Sun erwähnte Beispiel von Kamera und Drucker, die mit Jini über Netzwerk ihre jeweiligen Dienste zur Verfügung stellen und je nach Bedarf wechselseitig nutzen.
Die wesentliche Aufgabe für den Entwickler besteht zunächst darin, festzulegen wie das Gesamtsystem überhaupt arbeiten soll, was das System leisten soll und an welchen Stellen ggf. Eingriffe eines Bedieners vorzusehen sind. Die Dienste müssen konkret formuliert werden und es muß festgelegt werden, wie sie aufgerufen werden sollen.
Dabei reicht es aufgrund der modularen Struktur von Jini jedoch aus, zunächst die grundsätzliche Struktur sorgfältig vorzubereiten und die zentralen Dienste zu implementieren, da dann anschließend einfach und jederzeit weitere Dienste hinzugefügt werden können.
Für die Beispielimplementierung wurde auf einen Automatismus verzichetet, der ohne Bedienereingriff Aktionen auslöst (Fotografieren, Drucken etc.). Der Bediener muß die Aktionen selbst anstoßen.
Eine autonome Jini-Kamera sieht so aus: Die Kamera hat Anzeige- und Bedienelemente, mit denen ein Anwender die Kamera steuern kann. Sie hat einen Netzwerkanschluß und stellt über Jini Dienste (z.B. zum Bildabholen) zur Verfügung.
In der Beispielimplementierung ist die Jini-Kamera als Kombination aus Fotokamera und PC realisiert. Die Kamera ist über eine serielle Schnittstelle an ihren PC angeschlossen. Der PC realisiert die Anbindung per Jini an das Netzwerk. Die Kamera wird über das Java Native Interface (JNI) vom PC angesprochen. Als Anzeige- und Bedienelement der Kamera wird ein in Java geschriebenes Programm mit grafischer Bedienoberfläche verwendet.
Ein autonomer Jini-Drucker kann z.B. Bilder über Netzwerk entgegennehmen und ausdrucken. Er stellt über Jini Dienste im Netz zur Verfügung, z.B. zum Drucken von Bildern. Ein Jini-Drucker kann ebenfalls Anzeige- und Bedienelemente haben.
In der Beispielimplementierung ist der Jini-Drucker als Kombination aus Drucker und PC realisiert. Der Drucker ist an der parallel-Schnittstelle seines PCs angeschlossen. Der PC realisiert die Anbindung per Jini an das Netzwerk. Der Drucker wird vom PC über die normale Java-Schnittstelle angesprochen. Anzeige- und Bedienelemente für den Drucker sind derzeit nur als dummy implementiert.
Es gibt eine zusätzliche Bediensoftware, die den Auruf von Kamera-Diensten und Drucker-Dinsten ermöglicht und damit die Bedienung des Systems erlaubt, sowie ggf. den Aufruf weiterer Dienste zur Bildverarbeitung ermöglicht.
Derzeit ist diese Bediensoftware der einzige Dienste-Finder und Dienste-Nehmer im System. Ohne sie ist eine Verwendung der Jini-Dienste des Beispiels derzeit nicht möglich. Diese Komponente stellt aber nichts anderes dar, als die Fähigkeit einer Jini-Komponente, andere Jini-Dienste zu finden, dem Bediener zur Auswahl anzubieten und bei Bedarf aufzurufen.
Dieser Teil ließe sich entsprechend angepaßt in die Jini-Kamera integrieren, so daß der Bediener dort z.B. Druckdienste angeboten bekommt, wenn diese im Netz verfügbar sind. Im Jini-Drucker integriert könnte eine entsprechende Komponente z.B. nach Bildquellen suchen und diese per Menü zur Auswahl anbieten.
Abgesehen vom zusätzlichen Aufwand für Dienst-Anmeldung und -Suche beschränkt sich der Entwurf eines Jini-Dienstes auf den Entwurf einer Klasse mit Methoden der gewünschten Funktionalität.
Als Jini-Dienst können Objekte angemeldet werden, die java.io.Serializable implementieren. Unter Umständen vorteilhaft ist die Verwendung von Remote-Objekten zum Zugriff auf RMI-Server.
Da die Suche nach Jini-Diensten einerseits über eine Beschreibung der Dienste durch Texte in "ServiceInfo" und andererseits über vom Dienst implementierte Interfaces erfolgen kann, sind "ServiceInfo" und ggf. die Interfaces festzulegen. Die Entscheidung über die Interfaces wird bereits bei der Definition der Dienste benötigt. Die ServiceInfo wird erst beim Anmelden eines Objektes als Dienst benötigt.
Für das Beispiel wurde angenommen, daß sich die Dienste mit dem Erzeugen und Verarbeiten von Bildern befassen. Die Kamera kann als Bilderzeuger betrachtet werden, der Drucker als Bildverarbeiter. Demzufolge wurden folgende Interfaces entworfen.
public interface BildErzeuger {
public abstract ImageIcon gibAktuellesBild();
public abstract ImageIcon gibBild (BildInfo bi);
public abstract BildInfo zeigeBildListe();
}
public interface BildVerarbeiter {
public abstract void nimmBild (ImageIcon imic);
public abstract boolean zeigeBereitschaft();
}
Außerdem wurde eine Methode vorgesehen, um eine Bedienoberfläche (graphical user interface - GUI) aufzurufen. Unter dieser Methode kann man für jedes Jini-Gerät ein entsprechendes Anzeige- und Bedienteil als GUI implementieren, so daß der jeweilige Jini-Dienst gleich die Bedienoberfläche des Gerätes "mitbringt".
public interface Administrierer {
public abstract void zeigeAdminGUI();
}
Die Interfaces sind recht allgemein gehalten, so daß neben Kamera- und Druckdiensten weitere Dienste angeboten werden können. Dateisysteme und Bildbearbeitungsprogramme können z.B. sowohl als Bilderzeuger als auch als Bildverarbeiter auftreten.
(Anmerkung: O.g. Interfaces können auch als "extends java.rmi.Remote" definiert werden, wenn die Dienste direkt als RMI-Dienste verwendet werden sollen.)
Der Kameradienst wird durch die Klasse KameraDienstJini realisiert. Die o.g. Interfaces sind entsprechend implementiert. Das Interface "Runnable" stellt eine zusätzliche Möglichkeit zum Zugriff auf den Kameradienst dar. Unter "zeigeAdminGUI()" ist eine Bedienoberfläche für die Kamera implementiert, die auch fernbedientes Fotografieren ermöglicht.
public class KameraDienstJini
implements Runnable, BildErzeuger, Administrierer, java.io.Serializable
{ ... }
Als SereviceInfo zur Anmeldung als Jini-Dienst wird folgendes verwendet:
ServiceInfo srvInf = new ServiceInfo("KameraDienst", // name
"datelec GmbH", // manufacturer
"datelec GmbH", // vendor
"0.05ß", // version
"Demo", // model
"1.0"); // serialNumber
Der Zugriff auf die eigentliche Kamerasteuerung erfolgt per RMI. Dazu ist auf dem PC der Jini-Kamera ein RMI-Server gestartet, i.e. ein Objekt der Klasse "OlyControlSrv" unter dem Namen "OlyControlIF" bei der rmiregistry registriert.
KameraDienstJini stellt beim erstmaligen Aufruf einer Methode, die Zugriff auf die Kamera benötig (z.B. gibBild()) per Naming.lookup() Verbindung zum RMI-Server her. Bereits bei der Anmeldung als Jini-Dienst wird der dafür notwendige hostname an KameraDienstJini übergeben. Nach dem Verbindungsaufbau werden die benötigten Methoden des RMI-Servers aufgerufen.
Der Druckerdienst wird durch die Klasse DruckDienst realisiert. Der Methode "nimmBild()" kann ein Bild übergeben werden, das daraufhin ausgedruckt wird. "zeigeAdminGUI()" öffnet derzeit ein leeres Fenster, das keinerlei Bedienmöglichkeiten bietet.
public class DruckDienst extends UnicastRemoteObject
implements BildVerarbeiter, Administrierer
{ ... }
DruckDienst ist unmittelbar als RMI-Server konzipiert. Mit "extends UnicastRemoteObject" ist zugleich java.io.Serializable implementiert.
Kurioserweise arbeitet DruckDienst mit den übrigen Jini-Komponenten zusammen, obwohl die beiden implementierten Interfaces von der oben angeführten Definition abweichen. Für RMI-Zugriffe ist es nötig, Interfaces zu Implementieren, die als "extends java.rmi.Remote" definiert sind. Für DruckDienst wurden sowohl BildVerarbeiter wie auch Administrierer so definiert. Der Aufruf der jeweiligen Methoden (z.B. nimmBild()) bewirkt Zugriff per RMI auf ein Objekt der Klasse DruckDienst im Jini-Drucker-PC. Für eine "saubere" Anwendung wäre es nötig, sich auf eine einzige Definition der Interfaces festzulegen – entweder "extends java.rmi.Remote" oder eben nicht.
Die Methode main() von DruckDienst übernimmt beim Start auf dem Jini-Drucker-PC sowohl die Registrierung als RMI-Server bei der rmiregistry, als auch die Anmeldung als Jini-Dienst.
Als ServiceInfo wird verwendet:
ServiceInfo si = new ServiceInfo();
si.manufacturer = "Datelec GmbH und Herbert Bader";
si.model = "Druck";
si.name = "CamPrint";
si.serialNumber = "1";
si.vendor = "Datelec GmbH";
si.version = "1.0.0";
Der Betrachter-Dienst wird durch die Klasse BetrachterDienst realisiert. Der Methode "nimmBild()" kann ein Bild übergeben werden, das daraufhin in einem Fenster angezeigt wird.
public class BetrachterDienst
implements BildVerarbeiter, java.io.Serializable
{ ... }
Die Methode main() von BetrachterDienst meldet ein Objekt der Klasse BetrachterDienst als Jini-Dienst an. Beim Aufruf von nimmBild() wird das Bild an einen neues Objekt der Klasse Viewer zur Anzeige übergeben.
Als ServiceInfo wird verwendet:
ServiceInfo srvInf = new ServiceInfo("BetrachterDienst", // name
"datelec GmbH", // manufacturer
"datelec GmbH", // vendor
"0.01beta", // version
"Demo", // model
"1.0"); // serialNumber
Der Betrachter-Dienst kann von irgendeinem Jini-Rechner im Netz zur Verfügung gestellt werden, auf dem die von BetrachterDienst verwendeten Klassen vorhanden sind.
Das Starten aller benötigten Processe auf den beteiligten Rechnern erfolgt jeweils über Startscripten (z.B. "Batch-Dateien" beim PC). Das Starten der Jini-Kamera beschränkt sich somit auf das Einschalten des Rechners (und der Kamera) und den Aufruf des Startscripts. Entsprechendes gilt für den Jini-Drucker.
Das Aufrufen der Dienste geschieht (derzeit noch) über ein einen speziellen Lookup-Browser ("MyLookupBrowser"), der das Finden und den Aufruf der im Beispiel verwendeten Jini-Dienste ermöglicht. Der Browser enthält ein Menü, das dynamisch je nach Verfügbarkeit der Jini-Dienste aufgebaut wird. Durch Anwählen eines Menüpunktes wird der jeweilige Dienst aufgerufen.
Die Funktionalität diese Browsers ließe sich - wie bereits erwähnt - auch in die Bedienoberflächen der beteiligten Geräte integrieren, so daß auf den extra Browser verzichtet werden könnte.
[für Veröffentlichung gekürzt]
[...]
[...]
[...]
[...]
Das Automatische Starten der jeweils notwendigen Prozesse erfolgt, wie erwähnt, durch Startstcripts.
[...]
[...]
[...]
Einige Details zum Projektverlauf "Jini-Kamera" sind bisher in Notizen
- "Projektvarianten ‚Jini-Kamera‘" (12.05.1999),
- "Status und weiteres Vorgehen" (18.05.1999),
- "Notiz zum Status" (19.06.1999) und
- "Kurzstatus" (08.07.1999)
festgehalten.