Forum: PC-Programmierung JavaME Input Stream


von Su S. (sannchen)


Lesenswert?

Hallo Leute,

ich möchte ein Programm für ein Digitalfunkgerät schreiben.
Dieses soll seriell Daten ausgeben aber auch einlesen. Der Output Stream 
funktioniert, nur der Input Stream nicht.
Ich gebe in meinem Hyperterminal aufn PC Daten ein, aber das Programm 
sagt mir immer "Fehler: null", sprich das keine Daten ankommen.
1
 private void sendeDaten(byte[] b)
2
    {
3
        try
4
        {
5
            os = cc.openOutputStream();
6
            os.write(b);
7
            os.flush();
8
            os.close();
9
        }
10
        catch(IOException io)
11
        {
12
            textBox.setString("Fehler beim Senden der Daten: " + io.getMessage());
13
        }    
14
    }
15
    
16
    private void empfangeDaten()
17
    {
18
        try 
19
        {
20
            is = cc.openInputStream();
21
            byte[] data = new byte[150];
22
            int num;
23
            while(is.available() > 0) 
24
            {
25
    num = is.read(data, 0, data.length);
26
    textBox.setString("Empfange: "+ new String(data, 0, num));
27
            }
28
           is.close();
29
  }
30
        catch (IOException e) 
31
        {
32
            textBox.setString("Fehler beim Lesen empfangener Daten");
33
  }
34
    }
35
    
36
    private void open() 
37
    { 
38
      try
39
        {  
40
           cc= (CommConnection)Connector.open("comm:COM0");
41
 
42
            if(cc != null)
43
            {
44
                textBox.setString("Port offen"); 
45
                sendeDaten("AT D64A769F221E8".getBytes());
46
                empfangeDaten();                            
47
                cc.close();
48
                textBox.setString("Port geschlossen");        
49
            }
50
        }      
51
      catch(IOException io)
52
      {
53
           textBox.setString("Fehler " +io.getMessage());
54
      }
55
      finally
56
      {
57
          if (cc != null)
58
          {
59
             try
60
             {
61
                 cc.close(); 
62
                 os.close();
63
                 is.close();
64
             }
65
             catch(IOException e)
66
             {
67
                 textBox.setString("Fail: " + e.getMessage()); 
68
             }
69
          }
70
      }

Danke!
Sannchen

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

In deiner open Methode schließt du alles gleich wieder, das kann so 
nicht gut gehen.
Auch das Vermischen von GUI und Daten/Kommunikationscode ist nicht so 
schön.

Su Si schrieb:
> "Fehler: null", sprich das keine Daten ankommen

Das würde ich so nicht sagen, du greifst eher auf eine Variable zu 
welche null ist, also am besten mal den Stacktrace immer mit ausgeben 
und nicht nur lapidar die Meldung.

All diese Dinge haben übrigens gar nichts mit JavaME direkt zu tun, wie 
ich schon in einem anderem Thread schrieb, dir wird nichts anderes 
übrigbleiben als sich etwas mehr mit Java bzw. Programmieren allgemein 
zu beschäftigen sonst wird das nix.

von Su S. (sannchen)


Lesenswert?

Danke Läubi für deine Antwort! :)
Du meinst also, ich solle in der finally nicht den In- und Output Stream 
wieder schließen?
Wie solle ich es denn sonst machen?

Ich habe mich davor schon mit Java beschäftigt. Finde allerdings das 
sich das zu JavaME doch schon unterscheidet. Und leider bleibt mir nicht 
so viel Zeit mich damit noch neben her zu beschäftigen, da es für eine 
Bachelorarbeit ist.

Wie würdest du denn den Code umschreiben?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Die Streams und der Port müssen/sollten Member der Klasse sein, dan 
benötigst du für deine Klasse natürlich noch eine Close Methode welche 
ganz am ende des Programms aufgerufen wird (z.B. beim schließen der GUI 
oder als Shutdown-Hook).

Am besten lagert man das in eine eigene Klasse aus z.B. so:
1
public class SerialCommunicator implements Closeable {
2
3
  private final ExceptionListener listener;
4
  private CommConnection cc;
5
  private final String port;
6
  private BufferedReader is;
7
  private OutputStreamWriter os;
8
9
  public SerialCommunicator(String port, ExceptionListener listener) {
10
    this.port = port;
11
    this.listener = listener;
12
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
13
14
      @Override
15
      public void run() {
16
        SerialCommunicator.this.close();
17
      }
18
    }));
19
  }
20
21
  public void close() {
22
    closeSilent(cc);
23
    cc = null;
24
    closeSilent(is);
25
    is = null;
26
    closeSilent(os);
27
    os = null;
28
  }
29
30
  private void closeSilent(Closeable closeable) {
31
    if (closeable != null) {
32
      try {
33
        closeable.close();
34
      } catch (IOException e) {
35
        //ignore...
36
      }
37
    }
38
  }
39
40
  public boolean sendeDaten(String data) {
41
    try {
42
      if (os != null) {
43
        os.write(data);
44
        os.flush();
45
        return true;
46
      }
47
    } catch (IOException io) {
48
      listener.exceptionThrown(io);
49
    }
50
    return false;
51
  }
52
53
  public String empfangeDaten() {
54
    if (is != null) {
55
      try {
56
        return is.readLine();
57
      } catch (IOException e) {
58
        listener.exceptionThrown(e);
59
      }
60
    }
61
    return null;
62
  }
63
64
  public boolean open() {
65
    try {
66
      cc = (CommConnection) Connector.open(port);
67
      if (cc == null) {
68
        throw new IOException("Kann Port " + port + "nicht öffnen");
69
      } else {
70
        is = new BufferedReader(new InputStreamReader(cc.openInputStream()));
71
        os = new OutputStreamWriter(cc.openOutputStream());
72
        return true;
73
      }
74
    } catch (IOException io) {
75
      listener.exceptionThrown(io);
76
    }
77
    return false;
78
  }
79
}
In deiner GUI erzeugst du dir nun eine SerialCommunicator Objekt z.B. so
1
SerialCommunicator com = new SerialCommunicator("comm:COM0", new ExceptionListener() {
2
3
      @Override
4
      public void exceptionThrown(Exception e) {
5
        textBox.setString("Fehler " + e.getMessage());
6
        e.printStackTrace();
7
      }
8
    });
9
  com.open();
10
  com.sendeDaten("Hallo");
11
  String daten = com.empfangeDaten();
12
  textBox.setString("Empfangen: "+daten);
13
  com.close();
 und arbeitest dann mit diesem.

Su Si schrieb:
> Finde allerdings das
> sich das zu JavaME doch schon unterscheidet.

In dem ganzem Code gibt es eine Zeile welche JavaME spezifisch ist, 
der Rest ist plain Java.

Su Si schrieb:
> Und leider bleibt mir nicht so viel Zeit mich
> damit noch neben her zu beschäftigen, da es für
> eine Bachelorarbeit ist.

Vermutlich nicht für eine sonder für deine und somit gehört es 
entweder zu deiner Arbeit dazu, oder du musst dir vom Betreuer helfen 
lassen, das ist ja keine Forenarbeit oder?

von Su S. (sannchen)


Lesenswert?

Hey Läubi, danke für deine Hilfe und deinen Code!!

Mein Problem ist aber auch, dass das Funkgerät ein Midlet braucht, also 
noch diese Standardmethoden, welche ich beispielweise nicht in deinem 
Code sehe.
Und ich finde, dass unterscheidet sich auch zu Java.

Ja das stimmt, es ist meine Bachelorarbeit. Nur leider, kann mir mein 
Betreuer nicht sonderlich helfen. Deswegen habe ich gehofft, dass hier 
ein paar Leute mehr Erfahrung haben und mir helfen können. Und ich bin 
sehr glücklich und dankbar, dass du mir hilfst und Tipps gibst!!

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Su Si schrieb:
> Mein Problem ist aber auch, dass das Funkgerät ein Midlet braucht

In deinem Midlet kannst du doch aber Klassen verwenden welche keines 
sind. Man zwingt dich doch nicht alles in eine Klasse zu stopfen.

Deswegen schrieb ich ja das es wichtig ist wenigstens die Grundkonzepte 
verstanden zu haben. Und das kann man z.B. durch Bücher oder Tutorials 
fern ab der eigentlichen Aufgabe auch mal nebenbei in der "Freizeit" 
machen.

Su Si schrieb:
> Nur leider, kann mir mein
> Betreuer nicht sonderlich helfen.

In so einem Fall hilft es manchmal auch einfach mal Mitstudenten/innen 
um Hilfe zu bitten, vieles lässt sich im Gespräch einfacher klären als 
per PC Tastatur.

von Su S. (sannchen)


Lesenswert?

Das war mir bisher nich so klar. Ich ging davon aus, dass immer alles 
ein Midlet sein muss. Ich wurde mit dem Ganzen ins kalte Wasser geworfen 
und versuch jetzt mir das alles anzueignen und auf die Reihe zu 
bekommen.

Ich bin jetzt dabei deinen Code auszuprobieren. Allerdings meckert er 
immer beim BufferedReader obwohl den aus java.io.BufferedReader 
importiere. Und mit dem "addShutdownHook" hat er seine Probleme.

Da alle mit ihren Bachelorarbeiten genug zu tun haben, bleibt sowas 
leider auf der Strecke.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Su Si schrieb:
> Allerdings meckert er immer beim
> BufferedReader obwohl den aus
> java.io.BufferedReader importiere
Was meckert er?

Su Si schrieb:
> und mit dem "addShutdownHook" hat er seine Probleme
lass das erst mal weg, das war nur zum veranschaulichen, achte einfach 
darauf, dass es einen definierten Punkt gibt wo der Port geschlossen 
wird.

von Su S. (sannchen)


Lesenswert?

Das er den nicht findet und er möchte, dass ich ihn in einer Klasse 
erstelle. In der JavaME gibst den scheinbar auch nicht.
http://docs.oracle.com/javame/config/cldc/ref-impl/midp2.0/jsr118/index.html

oder kann ich eine ganze normale Javaklasse erstellen und diese im 
Midlet einbinden? Mir wurde bisher erzählt, dass das nicht geht.

Wenn ich das "addShutdownHook" weglasse, funktionieren das ganze 
Closeable nicht mehr.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Nur den Part weglöschen:
1
 Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
2
3
      @Override
4
      public void run() {
5
        SerialCommunicator.this.close();
6
      }
7
    }));

Su Si schrieb:
> In der JavaME gibst den scheinbar auch nicht

Dann nimm erst mal nur die Reader Klasse, dann musst du nur das lesen 
einer Zeile selbst implementieren.

Su Si schrieb:
> oder kann ich eine ganze normale Javaklasse erstellen und diese im
> Midlet einbinden? Mir wurde bisher erzählt, dass das nicht geht.

Warum sollte das nicht gehen? String, Inputstream, Outputstream, ... 
sind auch ganz 'normale' Klassen.

von Su S. (sannchen)


Lesenswert?

Ich werde es ausprobieren!

Dann schreibe ich das als normale Javaklasse.
Ich danke dir so sehr!!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.