# Erfahrung mit RXTX sowie Windows und Linux



## Eike (20. Aug 2008)

Hallo,
ich habe schon eine Frage zu rxtx und einer möglichen Alternative gestellt, aber es gibt wohl keine. Sie würde mein Problem wahrscheinlich auch nicht lösen.

Ich versuch es mal grob zu umreißen. Ich soll eine Wetterstation per SerialPort ansprechen. Unter Linux habe ich die Applikation fertig und es klappt alles wunderbar.
Unter Windows gibt es Rechner, da klappt es und es gibt Rechner, da klappt es gar nicht. Das Problem dabei ist, dass es keine Exceptions gibt, sondern einfach keine Daten im Inputstream des SerialPorts ankommen.

Ich habe schon auf der rxtx-Mailinglist nachgefragt, aber mehr als FlowControl-Einstellungen ändern konnten die mir bisher auch nicht sagen.

Weiß einer von euch Rat?

Welche Informationen benötigt ihr noch?

Die Wetterstation wird per SerialPort angesprochen:

```
while(true) aktivierungskommando schicken bis die Station antwortet
    daten abrufen
    daten verarbeiten 
// wiederhole 2 + 3 bis keine aktuellen Daten mehr vorhanden sind
daten ins netz schicken
```

So, das wäre es erstmal.

Für alle Befehle aus das Aktivieren nutze ich Events.


```
ArrayList<Record> data = new ArrayList<Record>(30);
		Configurations config = null;
		Date lastRecordedDate = null;
		int counter = 0;

		if(this.prepareForDownload().statusOK()){

			config = Configurations.instance();

			try {

				log.trace("lastRecordedDate  : " + config.getLastRecordDate());
				log.trace("lastRecordedblock#: " + WS2500Receiver.lastRecordBlockNumber);
				
				lastRecordedDate  = 
					Record.dateFormatter.parseISO8601String(config.getLastRecordDate());

			} catch (ParseException e) {

				log.error("date string \"" + config.getLastRecordDate() + "\" stored in configuration " +
				"could not be parsed");
				
				lastRecordedDate = new Date(0L); 
				
				log.error("lastRecordedDate is set to " + lastRecordedDate);
				
			}

			// this loop will download the data after activating the comm
			download:
				while(counter++ < this.maxRetries){
					boolean commActive = false;
					ActivateCommunication actComm;
					SelectFirstDataSet selFirst;
					GetDataSet getData;
					RecordImpl current;
					int counter_ = 0;
					long lastCommandSend;
					
					this.prepareForDownload();

					// 1 ACTIVATE COMMUNICATION
					while(!commActive && counter_++ < this.maxRetries){
						
						actComm = new ActivateCommunication(this.serialPort);
						actComm.send();

						commActive = actComm.getResult();						

					}
					if(counter_ == this.maxRetries || !commActive){
						log.error("could not activate communication with hws " +
								" via port \"" + this.serialPort.getName() + 
								"\"");

						break download;
					}
					counter_ = 0;

					log.debug("communication activated");

					// 2 DOWNLOAD FIRST DATASET

					do{
						getData = new GetDataSet(this.serialPort);
						getData.send();

						current = getData.getResult();
						getData = null;

					}while(current == null && counter_++ < this.maxRetries);

					// the download failed, 
					if(current == null){
						log.debug("could not download first dataset.");

						continue download;
					}

					if(current.equals(GetDataSet.NO_MORE_DATA)){
						log.info("no data in station memory");

						break download;
					}

					counter_ = 0;

					log.debug("downloaded first dataset: " + current);

					// 3 DOWNLOAD ALL NEW DATA
					download_new_data :
						while(lastRecordedDate.before(current.getTimeOfMeasurement())){
							SetPointerToNextRecord selNext;

							/*
							 *  3.1 CHECK_1
							 * we check the block number to add only new data to
							 * the result set
							 */
							if(current.getBlockNumber() != WS2500Receiver.lastRecordBlockNumber){
								data.add(current);
								WS2500Receiver.lastRecordBlockNumber = current.getBlockNumber();
								lastRecordedDate = current.getTimeOfMeasurement();

								log.debug("record added to resultset");
							}

							// 3.2 SET POINTER TO NEXT RECORD

							do{
								selNext = new SetPointerToNextRecord(this.serialPort);

								lastCommandSend = System.currentTimeMillis();
								selNext.send();

							}while(selNext.getResult() != SetPointerToNextRecord.DATA_AVAILABLE &&
									selNext.getResult() != SetPointerToNextRecord.NO_MORE_DATA &&
									counter_++ < this.maxRetries &&
									(System.currentTimeMillis() - lastCommandSend) < 500);

							if((System.currentTimeMillis() - lastCommandSend) > 500){
								log.debug("command send window closed(310)");
								// break download_new_data;
								continue download;
							}

							counter_ = 0;

							switch (selNext.getResult()) {
							case SetPointerToNextRecord.DATA_AVAILABLE:
								log.debug("pointer set to next dataset");

								// 3.3 DOWNLOAD NEW DATA
								do{
									getData = new GetDataSet(this.serialPort);
									lastCommandSend = System.currentTimeMillis();
									getData.send();

									current = getData.getResult();
									getData = null;

								}while(current == null && 
										counter_++ < this.maxRetries && 
										(System.currentTimeMillis() - lastCommandSend) < 500);

								if((System.currentTimeMillis() - lastCommandSend) > 500){
									log.debug("command send window closed(335)");
									continue download;
									//									break download_new_data;
								}

								if(current == null || counter_ == this.maxRetries){
									log.debug("no data received from station");

									break download;
								}

								if(current.equals(GetDataSet.NO_MORE_DATA)){
									log.debug("no more data in station memory");

									break download;
								}

								break;

							case SetPointerToNextRecord.NO_MORE_DATA:
								log.debug("no more data in station memory");

								// we are done, no more data in station
								break download;

							default:
								continue download; // restart from actComm
							}

						}

				} // END download_new_data
		} // END download
```
Hier noch ein Ausschnitt aus der prepareForDownload()-Methode.

```
String port = "";
		CommPortIdentifier portIdentifier;
		CommPort commPort;
		String errorMessage;

		try {

			port = Configurations.instance().getSerialPort();

			portIdentifier = CommPortIdentifier.getPortIdentifier(port);
			
			if(!portIdentifier.isCurrentlyOwned()){

				commPort = portIdentifier.open(this.getClass().getName(),2000);

				if (commPort instanceof SerialPort) {

					serialPort = (SerialPort) commPort;
					serialPort.setSerialPortParams(BAUDRATE, 
							DATABITS, 
							STOPBITS,
							PARITY);

					serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
```

Wird noch mehr Code benötigt?


----------



## schalentier (20. Aug 2008)

*autsch*... bist du sicher, dass Java das richtige fuer dich ist?


----------



## Eike (20. Aug 2008)

eine etwas differenziertere Antwort wäre dann echt mal schön!


----------



## tuxedo (21. Aug 2008)

Dein Stil ist einfach, sorry, ich sags mal auf gut deutsch, scheisse.

Die Sache mit den ganzen breaks und continue's ... Sowas macht man in Java und anderen objektorientierten Sprachen einfach nicht. 

Kleiner Tipp von meiner Seite:

Ich arbeite im Falle von RS232 kommunikation NIE mit Events. Warum? Gute Frage. Fand das von anfang an etwas "unschön" gelöst.

Ich hab stattdessen einen Thread dafür abgestellt der die Daten ausliest und der Anwendung, welche die Daten dann weiter ver/bearbeitet, bereitstellt. 

Könnte mir vorstellen dass das mit der Eventgeschichte bei dir halt nicht so funktioniert. 

Du solltest dringend deinen Code "umstrukturieren". Das ist absoluter Spaghetti-Code. Verwende richtige Methoden statt das mit switch/case/break/continues zu lösen. 

- Alex


----------



## Eike (26. Aug 2008)

Abgesehen vom schlechten Code (Spaghetti-Style) ist es leider so, dass auch nicht-eventbasierte Kommunikation mit dem SerialPort zu keiner Antwort führt.

Ich habe mir von Rechnern (Windows sowie Linux) die Einstellungen des Ports ausgeben lassen und sie sind auf beiden Rechnern gleich.

Mir erscheint es so, dass es an irgendwelchen Systemeinstellungen unter Windows liegt, habe aber keine Ahnung, an welchen...


----------



## tuxedo (26. Aug 2008)

Hast du das ganze mal in Hyperterminal in Windows getestet?


----------



## Eike (26. Aug 2008)

Nein, könntest du mir vielleicht ein paar entspr. Kommandos nennen bzw. eine gute Informationsquelle, wie ich die Wetterstation direkt via HyperTerminal ansprechen kann.


----------



## Saxony (26. Aug 2008)

Hiho,

1. win+r
2." hypertrm" eintippen
3. den ersten Wizard beenden
4. einrichtung neue Verbindung - pseudo Ortskennzahl eingeben
5. entsprechenden Com Port wählen
6. entsprechend dem Handbuch zu deinem Gerät mit diesem kommunizieren

bye Saxony


----------



## Eike (26. Aug 2008)

Wie kann ich denn bitte die Zahlenkombination 1 0 0 4 senden?

Die Verbindung konnte ich unter Windows XP herstellen, aber dann kann  ich nur Textdateien bzw. Dateien senden.

In Java schreibe ich das als byte[] einfach in den OutputStream.


----------



## tuxedo (26. Aug 2008)

>> Wie kann ich denn bitte die Zahlenkombination 1 0 0 4 senden? 

Einfach eintippen

>>In Java schreibe ich das als byte[] einfach in den OutputStream.

Wenn du mit 1 0 0 4 vier Bytes mit den Werten 1, zwei mal 0 und 4 meinst: Das wird etwas schwieriger. Da solltest du dann mit einem Hexeditor eine File mit diesen 4 Byte anlegen und die dann "senden".

- Alex


----------

