![]() |
[Studienarbeiten: Kommunikation zwischen PDAs] | ![]() |
Irchat wurde mit Hilfe von EIKON implementiert. EIKON ist das Standard GUI (Graphic User Interface) von EPOC32, und damit hat IrChat das typische Aussehen und 'Feeling' eines Psion Programms. Als Übertragungsprogramm für Texte und Dateien unterstützt IrChat auf dem Psion auch Point-To-Multipoint, mit dem es prinzipiell möglich ist, mit mehreren Geräten gleichzeitig verbunden zu sein.
Die Schnittstelle zum Benutzer bietet hauptsächlich ein großes Textfenster zur
Darstellung der empfangenen Meldungen, in dem der Benutzer auch selbst Eingaben oder
Entfernungen von Texten vornehmen kann. Eine weiteres, kleineres Textfenster unterhalb
davon dient zur Eingabe eigener Meldungen und spezieller Kommandos.
Ganz rechts befinden sich Schaltflächen für die wichtigsten Befehle, dazwischen eine
Leiste mit der Anzeige der verbundenen Geräte.Diese Anzeige dient mit ihren
Schaltflächen auch zum Aktivieren und Deaktivieren der Verbindungen (manchmal möchte der
Benutzer einen Text oder eine Datei vielleicht nicht allen verbundenen Geräten schicken).
Die Textfenster unterstützen natürlich das Kopieren, Ausschneiden und Einfügen von
Clipboard-Textdaten, dies ist wie üblich über eine Standardschaltfläche auf der linken
Seite erreichbar. Direkt darüber kann das Menü abgerufen werden; es erlaubt das
Speichern und Laden der Texte des Anzeigefensters, sowie einige Einstellungen, unter
anderem den Kurznamen, unter dem das Gerät bei der Kommunikation bekannt ist.
Die folgende Grafik zeigt diesen Sachverhalt noch einmal:
Das Menü bietet die folgenden Kommandos:
Menü | Untermenü | Beschreibung |
File | Create new file | Erzeugt ein leeres Anzeigefenster |
Open file | Öffnet ein gespeichertes Anzeigefenster | |
More/Save As & More/Save | Speichert das Anzeigefenster | |
Close | Beendet das Programm | |
Edit | Cut | Schneidet die Auswahl in die Zwischenablage |
Copy | Kopiert die Auswahl in die Zwischenablage | |
Paste | Fügt die Zwischenablage ein | |
Select all | Wählt den gesamten Text des Anzeigefensters | |
Delete/Delete all | Löscht die Auswahl bzw. das gesamte Anzeigefenster | |
View | Show toolbar | Zeigt oder versteckt die rechte Menüleiste |
Show top toolbar | Zeigt oder versteckt die obere Menüleiste | |
Tools | Preferences | Erlaubt die Wahl des Namens und des Hintergrunds |
Start server | Startet den Server mit aktuellem SLSAP-SEL | |
Stop server | Stopt den Server | |
Status | Zeigt Serverstatus und Verbindungen an | |
Scan only | Führt einen Scan nach anderen Geräten durch ohne zu verbinden | |
Help on IRCHAT | Zeigt eine kleine Hilfe an | |
About IRCHAT | Zeigt die About-Box an |
Wie schon erwähnt, lassen sich über die Eingabe weitere Kommandos abrufen, die nun
kurz vorgestellt werden.
Jedes dieser Kommandos beginnt mit einem Ausrufezeichen und hat vier Buchstaben
Führt einen IAS-Query aus,
d.h. die Datenbank eines anderen Gerätes wird nach einem Attribut einer angegebenen
Klasse gefragt. Dies ist momentan im Programm nur mit schon verbundenen Geräten möglich,
theoretisch gehts auch mit nicht verbundenen Geräten.
Klassenname | gibt den Namen der Klasse an, in der gesucht werden soll |
Attributname | gibt den Namen des Attributs an, das gesucht werden soll |
Nummer der Verbindung | die nullbasierte Nummer des verbundenen Gerätes. |
Registriert einen Eintrag in die Datenbasis des eigenen Gerätes. Momentan sind nur
Zahlen als Eintrag möglich.
Klassenname | in welche Klasse soll eingetragen werden? |
Attributname | in welches Attribut der Klasse? |
Eintrag | eine Nummer, die eingetragen werden soll |
Stopt den Server, d.h. läßt keine Verbindung von außen mehr zu.
Startet den Server. Ist dieser schon am Laufen, wird er zuvor gestoppt. Der LSAP-SEL gibt den lokalen LSAP an, auf den ein Gerät von außen zugreifen kann.
Setzt für einen Verbindungsversuch den LSAP-SEL
fest, der benutzt werden soll. Dieser muß mit dem LSAP-SEL
der Maschine übereinstimmen, zu dem verbunden werden soll.
IrChat unter EPOC32 läßt sich in zwei Teile spalten. Die Benutzeroberfläche,
realisiert unter EIKON, und die Schnittstelle zu IrDA (das Programm verwendet im moment
grundsätzlich IrTinyTP). Diese Schnittstelle, realisiert als
Objekt CIrdaIF (in der Datei irif.cpp, Deklaration in irif.h)
muß von einer Klasse der Applikation bzw. Oberfläche erzeugt werden. Bevor die
Funktionen der Klasse genutzt werden können, muß per CIrdaIF::init() ein Zeiger auf ein CIrdaIFObserver Objekt übergeben werden.
Dieses erhält in Zukunft alle Meldungen und Informationen von der Schnittstelle. CIrdaIFObserver ist eine rein abstrakte Klasse, d.h. eine
beliebige Klasse der Applikation muß (unter anderem) von ihr erben und ihre Funktionen
überschreiben. Als dritte Klasse ist schließlich noch CConnection deklariert. Diese
Klasse repräsentiert eine einzelne Verbindung zu einem anderen Gerät, ist aber
für einen Benutzer der Schnittstelle nicht wichtig.
Hinweise zu den in der Definition benutzten Klassen:
TBool ist unter EPOC eine Klasse für bool'sche Werte, TInt eine 32-bit Zahl. Eine
TDes-Klasse steht für einen Speicherbereich (normalerweise einen Text), TDesC ist die
konstante Version davon.
Wie schon erwähnt, müssen alle Funktionen von der Schnittstellennutzerklasse
überschrieben werden. Alle Texte haben am Schluß kein Zeilenende. Es ist Aufgabe des
Observers, sich hierum zu kümmern.
Im Falle von IrChat gibt NewMessage() den Text in das Anzeigefenster, InfoMessage gibt ein
kurzlebiges Infofeld im oberen rechten Eck des Psion aus, und
ErrorMessage() erzeugt ein Hinweisfenster mit der übergebenen Meldung, das aktiv
geschlossen werden muß.
Eine etwas sauberere Lösung ist das Übergeben eines Fehler/Statuscodes bei InfoMessage
und ErrorMessage. Darauf wurde im Falle von IrChat der Einfachheit halber verzichtet.
virtual void NewMessage(TInt devNum, const TDesC& aText) | Wird aufgerufen, falls eine Nachricht (aText) vom Gerät mit der Kennziffer devNum
erhalten wird. Ist devNum -1, so ist die Meldung allgemein. Ist devNum -2, so soll die Meldung noch nicht mit einem Zeilenende abgeschlossen werden. |
virtual void InfoMessage(const TDesC& aText) | Gibt eine Statusmeldung (Z.B. ein Verbindungsende) an |
virtual void ErrorMessage(const TDesC& aText) | Wird aufgerufen, wenn ein Fehler aufgetreten ist |
virtual void ConnectionsChanged() | Die Anzahl oder der Name von Verbindungen hat sich geändert, bspw. nach einer Suche |
TBool Init(CIrdaIFObserver* pObserver,TBool startserver=ETrue); | Muß zu Beginn aufgerufen werden. Übergibt den Observer und legt fest, ob der Server sofort starten soll. |
TInt Scan(TBool DoConnect=ETrue); | Sucht nach anderen Geräten und versucht sich, falls DoConnect wahr ist, mit diesen zu verbinden. |
TInt GetDeviceCount(); | Gibt die Anzahl der verbundenen Geräte aus |
TBool GetDeviceName(TInt devNum, TDes& aName); | Trägt den Namen des Gerätes in aName ein, devNum gibt die nullbasierte Kennziffer des Geräts an |
void PrintStatus(); | Gibt über CIrdaIFObserver::Newmessage() eine Reihe von Statusmeldungen aus. |
void IASQuery(TDesC8 &aClassName,TDesC8 &aAttributeName,TInt devNum); | Führt eine IAS-Abfrage durch. Ist im Moment nur mit verbundenen Geräten möglich (wird über devNum angegeben) |
void IASRegistration(TDesC8 &aClassName,TDesC8 &aAttributeName,TInt value); | Trägt einen Wert in die eigene Datenbasis ein. Momentan sind nur Ganzzahleneinträge möglich. |
TBool SendToDevice(TInt devNum, const TDesC& aText); | Sendet eine Nachricht an ein angegebenes Gerät |
TBool SendToActiveDevices(const TDesC& aText); | Sendet eine Nachricht an alle aktiven Geräte |
void ActivateDevice(TInt devNum,TBool bactivate = ETrue); | Aktiviert oder deaktiviert ein angegebenes Gerät, je nach wert von bactivate. |
TBool IsDeviceActive(TInt devNum); | Gibt zurück, ob ein Gerät aktiv ist. |
void StopServer(TBool silent=EFalse); | Hält den Server an. Ist silent wahr, so erfolgt dabei keine Statusmeldung |
TBool StartServer(TInt homeport=0); | Startet den Server. Ist homeport null, so wird der alte SLSAP-SEL benutzt. Ansonsten wird homeport als neuer SLSAP-SEL gewertet. |
void SetDLSAPSEL(TInt dsel); | Setzt den DLSAP-SEL, um einen Verbindungsaufbau bei abweichernder SLSAP-SEL des Zielgeräts zu ermöglichen |
TInt GetNextFileReceive(TDes& Filename); | Liefert die Kennziffer des nächsten Gerätes, das eine Datei zusenden will. Filename wird mit dem Namen der Datei gefüllt. Liefert -1, falls gerade kein Gerät eine Datei zusenden will. |
void StartFileTransfer(TInt devNum,TDes& fileName,TBool Start); | Startet einen Filetransfer. Ist devNum kleiner Null, so wird ein File (filename gibt den Ordner und die Datei an) an alle aktiven Verbindungen geschickt, ansonsten wird ein File von einem anderen Gerät empfangen und unter filename gespeichert, falls Start wahr ist. Im anderen Fall wird das File abgelehnt. |
void SetNickName(TDesC& nickname); | Setzt den eigenen Namen und informiert die anderen Geräte |
Zur Verdeutlichung einiger grundlegender Prinzipien unter EPOC werden nun ein paar
Zeilen des Sourcecodes genauer beschrieben.
m_log().iAddr.SetPort(dlsapsel);
TRequestStatus stat,statTimer;
RTimer tim;
tim.CreateLocal();
m_socket.Connect(m_log().iAddr,stat);
tim.After(statTimer,5000000L);
User::WaitForRequest(stat,statTimer);
if (statTimer.Int()==KErrNone)...
Obige Programmzeilen beschreiben den Verbindungsaufbau der CConnection Klassen. m_log
enthält eine Addresssklasse iAddr, die das Ziel der Verbindung enthält.
Als erstes wird in dieser Addresse noch der Zielport (DLSAP-SEL) eingetragen.
TRequestStatus repräsentiert einen Status für eine asynchrone Operation.
Diese sind im Beispiel RSocket::Connect() und RTimer::Afer(). Beide Funktionen blockieren
den Programmablauf nicht, sind aber auch nach Ausführung noch nicht beendet. Connect()
verbindet zu einem anderen Gerät, After() wartet eine bestimmte Zeit. Um zu überprüfen,
ob ein asynchroner Aufruf beendet ist, muß der Funktion also ein Status übergeben
werden. Dieser wird beim Aufruf auf den Wert KRequestPending gesetzt, d.h. Die Ausführung
dauert noch an.
Connect() setzt in dem Status einen Fehler oder ein KErrNone (kein Fehler), sobald
es durchgeführt ist. After() setzt das KErrNone nach den angegebenen
Mikrosekunden. Die Funktion WaitForRequest, der die beiden Statusvariablen übergeben
werden, wartet nun (blockierend) darauf, daß einer der beiden Befehle beendet wird.
Später kann über den Wert der Variablen festgestellt werden, welcher Aufruf zuerst
erfolgreich abgeschlossen wurde. Obiges Programmfragment implementiert also einen fünf
Sekunden Time-Out für die Verbindung, d.h. nach fünf Sekunden wird der
Verbindungsversuch automatisch abgebrochen.
Send() und Receive(), Funktionen von RSocket zum Datenaustausch, haben ebenfalls diese
Statusvariablen. In einer Idlefunktion von CIrdaIF werden die Statusvariablen aller
Verbindungen, die einen Receive ausführen, überprüft, ob in der Zwischenzeit eine
Meldung angekommen ist. Ist dies der Fall, werden die Werte ausgelesen und der beendete
Receive neu ausgeführt. Eine Aufspaltung in Threads wie unter Windows CE ist also trotz
mehrfacher Verbindungsmöglichkeit nicht nötig.
Deklaration in irif.h, Definition in irif.cpp
Die Konfigurationsdatei zur Erzeugung von IrChat ist IrChat.mmp.
Falls als Verzeichnis nicht \EPOC32EX\IRCHAT gewählt wurde, muß dies in dieser Datei
eingetragen werden. Danach lassen sich Projektdateien für Visual C++ unter Windows 95
oder NT erstellen. Dazu ist der Aufruf von makmake nötig.
Die Kommandozeile lautet: makmake irchat vc4 bzw makmake irchat vc5. Das
Programm erzeugt dann eine Projektdatei (irchat.dsp) die in Visual C++ eingeladen werden
kann. EPOC32 verfügt über einen Emulator unter Windows, der leider keine Programme
ausführen kann, die auf die Infrarotschnittstelle zugreifen (Absturz). Dieser ist (unter
Ausschließung der IrDA-Komponenten) also nur zum leichten Programmieren der
Benutzeroberfläche nützlich.
Um die Applikation für den Psion zu erstellen, ist das Kommando makmake irchat marm
notwendig. Dieses erzeugt das File irchat.marm, mit dem dann per nmake -f irchat.marm
die Programmdatei (und die Resourcedatei) erstellt werden kann. Diese sind übrigens im
\EPOC32\RELEASE\MARM\REL zu finden und müssen dann in ein Verzeichnis IrChat unter
\System\Apps auf den Psion kopiert werden. (Die Namen der Dateien lauten irchat.app und
irchat.rsc).
Wichtig für das Laufen des Programms auf dem Psion ist, falls noch nicht
vorhanden, die Installation der Standard-C-Bibliothek (estlib.dll) ins Verzeichnis
\SYSTEM\LIBS. Bleibt noch anzumerken, das zu Erstellung notwendige Verzeichnisse mit makemake
-makework irchat marm bzw. makemake -makework irchat vc4 erstellt werden
können.
Das Programm reagiert mit einer Fehlermeldung, falls auf die Infrarotschnittstelle
nicht zugegriffen kann. Der Psion unterstützt nicht gleichzeitig eine Kabel- und
Infrarotverbindung. Über das Steuermenü bzw. CTRL-L läßt sich auf dem Psion die
korrekte Einstellung vornehmen.
![]() |
[Studienarbeiten: Kommunikation zwischen PDAs] | ![]() |