String in dez umwandel oder bitweise verschieben

Shortyyyy

Grünschnabel
Hallo liebe Profis..

Beschäftige mich schon seit mehreren Tagen damit von OBD Daten auszulesen, das klappt auch schon recht gut. Das Programm hat folgende Idee.
Ich greife über eine serielle Schnittstelle auf mein Steuergerät zu. Das funktioniert mit den Modembefehlen, atz usw.

Ein Beispiel ist die Motordrehzahl auszulesen.
Diese wird mit dem Befehl
010C
abgefragt. Als Antwort erhalte ich
41 0C 2C 20 <- ( auch mit den Leerzeichen dazwischen)

Die Antwort ist wie folgt aufgebaut.
41 0C ist einfach nur die wiederholte Anfrage und 2C 20 die eigentlichen Daten. So und nun zu meinem Problem.
Da die Ausgabe nur in einem String ist, möchte ich
1. erst beim 3 Byte anfangen zu zählen und 2. das Leerzeichen (zwischen 2C und 20) weglassen.
So das ich dann 2C20 als Antwort habe um diesen dann in Dezimal umrechnen kann.
Das Ergebniss sollte dann 11296 sein.
Und genau um diese Umrechnung geht es...
PS. nicht wundern das die Drehzahl so hoch ist, diese wird am Schluss noch durch 4 geteilt, aber dies sei jetzt mal so dahingestellt.

Ich hoffe ihr hättet da eine Idee wie man das realisieren könnte.

hier mal der Quellcode
Hier steht die Ausgabe vom String ( heißt junk)
Code:
import java.awt.*;
import java.io.*;

import javax.comm.*;


/**
 * Subclasses CommPortOpen and adds send/expect handling for dealing with
 * Hayes-type modems.
 * 
 */
public class CommPortModem extends CommPortOpen {
	/** The last line read from the serial port. */
	protected String response;
	/** A flag to control debugging output. */
	protected boolean debug = true;
	
	public CommPortModem(Frame f) throws IOException, NoSuchPortException,
			PortInUseException, UnsupportedCommOperationException {
		super(f);
	}

	/**
	 * Send a line to a PC-style modem. Send \r\n, regardless of what platform
	 * we're on, instead of using println().
	 */

 
	protected void send(String s) throws IOException {
		if (debug) {
			System.out.print("\tAnfrage: " + s);
			System.out.println();
		}
		os.print(s);
		os.print("\r\n");
		// Expect the modem to echo the command.
		if (!expect(s)) {
			System.err.println("WARNING: Modem did not echo command.");
			}
		// The modem sends an extra blank line by way of a prompt.
		// Here we read and discard it.
		
		String junk = is.readLine();

		System.out.println("\tAntwort: " + junk);              //HIER IST DIE AUSGABE DES   STRINGS

	}
	/**
	 * Read a line, saving it in "response".
	 * 
	 * @return true if the expected String is contained in the response, false
	 *         if not.
	 */
	protected boolean expect(String exp) throws IOException {

		response = is.readLine();

		if (debug) {
		
		}
		return response.indexOf(exp) >= 0;
	}
}

Hier ist die Anfrage (das 010C)
Code:
import java.io.*;
import java.security.Timestamp;
import java.util.Timer;
import java.util.TimerTask;

import javax.comm.*;


/**
 * Dial a phone using the Java Communications Package.
 * 
 */
public class CommPortDial extends CommPortModem {

	boolean bed = true;

	public static void main(String[] ap) throws IOException,
			NoSuchPortException, PortInUseException,
			UnsupportedCommOperationException {

		new CommPortDial().converse();
		System.exit(0);
		
	}

	public CommPortDial() throws IOException, NoSuchPortException,
			PortInUseException, UnsupportedCommOperationException {
		super(null);

	}

	protected void converse() throws IOException {

		// Send the reset command

		System.out.println(new java.sql.Timestamp(new java.util.Date().getTime()));
		send("010C");
		expect("OK");
	}
}

Ich wäre euch zu tiefst dankbar, denn ich hänge schon so lange dran und es will einfach nicht klappen.

MFG
Shortyyyy
 
Zuletzt bearbeitet:
Hi,

versuch mal das hier:

Code:
String junk = "41 0C 2C 20";
String sub = test.substring(6);    // "2C 20"
String cleaned = sub.replaceAll(" ", "");    // "2c20"

int result = Integer.parseInt(cleaned,16);    // 11296

MfG,
DarkWizzard
 
Und für den Fall dass der Befehl auch mal länger sein kann, könnte man die über mir gezeigten Funktion folgendermaßen umbauen:
Java:
public int convert(String command, String result) {
	return Integer.parseInt(result.replaceAll(" ", "").substring(
			command.length()), 16);
}
Anwendungsbeispiel:
Java:
String command = "010C";
String result = "41 0C 2C 20";

System.out.println(convert(command, result));

// Output: 11296
 
@Tsunamii

Danke. Vielen Dank es läuft super :) oh man Stunden der Arbeit. Ich danke dir vielmals.
Jedoch eine Frage habe ich jetzt noch und zwar ich habe mehrere Ausgaben.

Sprich ich habe:
- Temperatur (Abfrage mit 0105)
- Geschwindigkeit (Abfrage mit 010D)
usw.

Das Problem ist das es ja nicht der realle Wert ist denn ich da wiedergebe, sondern dieser erst noch berechnet werden muss.
Wie mache ich dann sowas variabel das erst zum beispiel erkennt das wenn ich die Temp. abfrag (0105)
das er mir dann automatisch 40 wegrechnet.
Bei der Drehzahl (010C) am schluss durch 4 teilt.
 
hm hört sich für mich so an als wenn man dann für jede Berechnung eine eigene Funktion bräuchte, da die Unterschiede doch ein wenig größer sind.

Hierzu könnte man zum Beispiel das Kürzen des Ausgabestrings erst einmal auslagern. Z.B. so:
Java:
public int getIntValue(String command, String result) {
    return Integer.parseInt(result.replaceAll(" ", "").substring(
            command.length()), 16);
}
Dann braucht man für die einzelnen Ausgaben, nur noch die jeweilige Berechnung anfügen:
Java:
public int getDrehzahl(String command, String result) {
     return getIntValue(command, result) / 4;
}

public int getTemperatur(String command, String result) {
     return getIntValue(command, result) - 40;
}

...

Falls mir noch was kürzeres einfällt sag ich bescheid ;)
 
@Tsunamii

wiedermal vielen DANK für deine Hilfe. Es funktioniert auch, ABER ich weiß nicht genau wie is es in meinen Code einbinden soll. Hier mal mein Code wie ich es eingebaut habe, aber so gibt er mir bis jetzt nur die richtige Drehzahl an, sobald ich denn zweiten "getTemperatur" in die Ausgabe gebe wo jetzt auch getDrehzahl steht gibt es mir falsche Ergebnisse aus.

Hier mal der code
Code:
import java.awt.*;
import java.io.*;

import javax.comm.*;
import java.security.Timestamp;
import java.util.Timer;
import java.util.TimerTask;
/**
 * Subclasses CommPortOpen and adds send/expect handling for dealing with
 * Hayes-type modems.
 * 
 */
public class CommPortModem extends CommPortOpen {

	/** The last line read from the serial port. */
	protected String response;
	/** A flag to control debugging output. */
	protected boolean debug = true;

	public CommPortModem(Frame f) throws IOException, NoSuchPortException,
			PortInUseException, UnsupportedCommOperationException {
		super(f);
	}

	/**
	 * Send a line to a PC-style modem. Send \r\n, regardless of what platform
	 * we're on, instead of using println().
	 */

	public int getIntValue(String command, String result) {
	    return Integer.parseInt(result.replaceAll(" ", "").substring(
	            command.length()), 16);
	}
	protected void send(String s) throws IOException {

		if (debug) {
			if(s == "010D"){
				System.out.print("\tAnfrage: " + s + "\t\t\tGeschwindigkeit");
			}if(s == "010C"){
				System.out.print("\tAnfrage: " + s + "\t\t\tDrehzahl");
			}if(s == "0105"){
				System.out.print("\tAnfrage: " + s + "\t\t\tTemperatur");
			}
			System.out.println();
		}
		os.print(s);
		os.print("\r\n");
		// Expect the modem to echo the command.
		if (!expect(s)) {
			System.err.println("WARNING: Modem did not echo command.");
		}
		// The modem sends an extra blank line by way of a prompt.
		// Here we read and discard it.

		String junk = is.readLine();

		String command = s;
		String result = junk;

		System.out.println("\tAntwort: " + junk + "\t\tRichtig Wert:  "
				+ getDrehzahl(command, result)  + "\t\t"
				+ new java.sql.Timestamp(new java.util.Date().getTime()));
		System.out.println();
	}

	/**
	 * Read a line, saving it in "response".
	 * 
	 * @return true if the expected String is contained in the response, false
	 *         if not.
	 */
	public int getDrehzahl(String command, String result) {
	     return getIntValue(command, result) / 4;
	}
	 
	public int getTemperatur(String command, String result) {
	     return getIntValue(command, result) - 40;
	}

	protected boolean expect(String exp) throws IOException {

		response = is.readLine();

		if (debug) {

		}
		return response.indexOf(exp) >= 0;
	}
}
 
also ich hätte es jetzt so gelöst, weiß aber nicht ob es eleganter geht.
Code:
import java.awt.*;
import java.io.*;

import javax.comm.*;
import java.security.Timestamp;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Subclasses CommPortOpen and adds send/expect handling for dealing with
 * Hayes-type modems.
 * 
 */
public class CommPortModem extends CommPortOpen {

	/** The last line read from the serial port. */
	protected String response;
	/** A flag to control debugging output. */
	protected boolean debug = true;

	public CommPortModem(Frame f) throws IOException, NoSuchPortException,
			PortInUseException, UnsupportedCommOperationException {
		super(f);
	}

	/**
	 * Send a line to a PC-style modem. Send \r\n, regardless of what platform
	 * we're on, instead of using println().
	 */
	public int convert(String command, String result) {
	    return Integer.parseInt(result.replaceAll(" ", "").substring(
	            command.length()), 16);
	}
	public int getIntValue(String command, String result) {
		return Integer.parseInt(result.replaceAll(" ", "").substring(
				command.length()), 16);
	}

	protected void send(String s) throws IOException {

		if (debug) {

			if (s == "010C") {
				System.out.print("\tAnfrage: " + s + "\t\t\tDrehzahl");
			}
			if (s == "0105") {
				System.out.print("\tAnfrage: " + s + "\t\t\tTemperatur");
			}
			if (s == "010D") {
				System.out.print("\tAnfrage: " + s + "\t\t\tGeschwindigkeit");
			}
			System.out.println();
		}
		os.print(s);
		os.print("\r\n");
		// Expect the modem to echo the command.
		if (!expect(s)) {
			System.err.println("WARNING: Modem did not echo command.");
		}
		// The modem sends an extra blank line by way of a prompt.
		// Here we read and discard it.

		String junk = is.readLine();

		String command = s;
		String result = junk;
		if (s == "0105") {
			System.out.println("\tAntwort: " + junk + "\t\tRichtig Wert:  "
					+ getTemperatur(command, result) + "\t\t"
					+ new java.sql.Timestamp(new java.util.Date().getTime()));
		}		if (s == "010C") {
			System.out.println("\tAntwort: " + junk + "\t\tRichtig Wert:  "
					+ getDrehzahl(command, result) + "\t\t"
					+ new java.sql.Timestamp(new java.util.Date().getTime()));
		}		if (s == "010D") {
			System.out.println("\tAntwort: " + junk + "\t\tRichtig Wert:  "
					+ getGeschwindigkeit(command, result) + "\t\t"
					+ new java.sql.Timestamp(new java.util.Date().getTime()));
		}
		System.out.println();
	}

	/**
	 * Read a line, saving it in "response".
	 * 
	 * @return true if the expected String is contained in the response, false
	 *         if not.
	 */
	public int getDrehzahl(String command, String result) {
		return getIntValue(command, result) / 4;
	}

	public int getTemperatur(String command, String result) {
		return getIntValue(command, result) - 40;
	}
	public int getGeschwindigkeit(String command, String result) {
		return getIntValue(command, result);
	}

	protected boolean expect(String exp) throws IOException {

		response = is.readLine();

		if (debug) {

		}
		return response.indexOf(exp) >= 0;
	}
}
 
ok hier mal eine idee wie man es eventuell eleganter lösen kann, jedoch ist diese Lösung etwas komplexer.

zu erst kannst du die Funktion convert aus deinem Code entfernen da sie nicht mehr benutzt wird und durch die Funktion darunter ersetzt wurde.

Dann würde ich eine HashMap sowie eine Konstanten einbauen um die if-Abfragen für die Befehle in schönere switch-case Konstrukte umzubauen

Beispiel:
Java:
public static final int TEMPERATUR = 1;
public static final int DREHZAHL = 2;
public static final int GESCHWINDIGKEIT = 3;

public static final HashMap<String, Integer> MAP;
static {
     MAP = new HashMap<String, Integer>();
     MAP.put("0105", TEMPERATUR);
     MAP.put("010C", DREHZAHL);
     MAP.put("010D", GESCHWINDIGKEIT);
}
Nun lassen sich die if-Blöcke durch folgende Konstrukte ersetzen
Java:
if (s == "010C") {
                System.out.print("\tAnfrage: " + s + "\t\t\tDrehzahl");
            }
            if (s == "0105") {
                System.out.print("\tAnfrage: " + s + "\t\t\tTemperatur");
            }
            if (s == "010D") {
                System.out.print("\tAnfrage: " + s + "\t\t\tGeschwindigkeit");
            }
            System.out.println();
wird zu
(ist gekürzt also bitte nicht 1zu1 übernehmen^^)
Java:
switch(MAP.get(s)) {
case TEMPERATUR:
     System.out.println("\tAnfrage .... Temperatur");
     break;
case DREHZAHL:
     System.out.println("\tAnfrage .... Drehzahl");
     break;
case GESCHWINDIGKEIT:
     System.out.println("\tAnfrage .... Geschwindigkeit");
     break;
}
und
Java:
        if (s == "0105") {
            System.out.println("\tAntwort: " + junk + "\t\tRichtig Wert:  "
                    + getTemperatur(command, result) + "\t\t"
                    + new java.sql.Timestamp(new java.util.Date().getTime()));
        }       if (s == "010C") {
            System.out.println("\tAntwort: " + junk + "\t\tRichtig Wert:  "
                    + getDrehzahl(command, result) + "\t\t"
                    + new java.sql.Timestamp(new java.util.Date().getTime()));
        }       if (s == "010D") {
            System.out.println("\tAntwort: " + junk + "\t\tRichtig Wert:  "
                    + getGeschwindigkeit(command, result) + "\t\t"
                    + new java.sql.Timestamp(new java.util.Date().getTime()));
        }
        System.out.println();
wird zu
Java:
int richtig = -1;
switch(MAP.get(s)) {
case TEMPERATUR:
     richtig = getTemperatur(command, result);
     break;
case DREHZAHL:
     richtig = getDrehzahl(command, result);
     break;
case GESCHWINDIGKEIT:
     richtig = getGeschwindigkeit(command, result);
     break;
}
System.out.println("\tAntwort: " + junk + "\t\tRichtiger Wert: " + richtig + "\t\t" + new Date());
 
Guten Morgen!
Vielen dank Tsunamii für deine ausführliche Beschreibung, jedoch funktioniert es noch nicht so viel gewollt.

Hab folgende Fehlermeldung:
Code:
Trying to open COM3...
	Anfrage: 0105			Drehzahl
WARNING: Modem did not echo command.
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -4
	at java.lang.String.substring(String.java:1937)
	at java.lang.String.substring(String.java:1904)
	at CommPortModem.getIntValue(CommPortModem.java:37)
	at CommPortModem.getTemperatur(CommPortModem.java:57)
	at CommPortModem.send(CommPortModem.java:93)
	at CommPortDial.converse(CommPortDial.java:35)
	at CommPortDial.main(CommPortDial.java:18)

hab es so eingebaut.
Code:
import java.awt.*;
import java.io.*;

import javax.comm.*;
import java.security.Timestamp;
import java.sql.Date;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Subclasses CommPortOpen and adds send/expect handling for dealing with
 * Hayes-type modems.
 * 
 */


public class CommPortModem extends CommPortOpen {

	/** The last line read from the serial port. */
	protected String response;
	/** A flag to control debugging output. */
	protected boolean debug = true;

	public CommPortModem(Frame f) throws IOException, NoSuchPortException,
			PortInUseException, UnsupportedCommOperationException {
		super(f);
	}

	/**
	 * Send a line to a PC-style modem. Send \r\n, regardless of what platform
	 * we're on, instead of using println().
	 */
	

	public int getIntValue(String command, String result) {
		return Integer.parseInt(result.replaceAll(" ", "").substring(
				command.length()), 16);
	}

	public static final int TEMPERATUR = 1;
	public static final int DREHZAHL = 2;
	public static final int GESCHWINDIGKEIT = 3;
	 
	public static final HashMap<String, Integer> MAP;
	static {
	     MAP = new HashMap<String, Integer>();
	     MAP.put("0105", TEMPERATUR);
	     MAP.put("010C", DREHZAHL);
	     MAP.put("010D", GESCHWINDIGKEIT);
	}
	public int getDrehzahl(String command, String result) {
		return getIntValue(command, result) / 4;
	}

	public int getTemperatur(String command, String result) {
		return getIntValue(command, result) - 40;
	}
	public int getGeschwindigkeit(String command, String result) {
		return getIntValue(command, result);
	}
	protected void send(String s) throws IOException {

		switch(MAP.get(s)) {
		case TEMPERATUR:
				System.out.print("\tAnfrage: " + s + "\t\t\tDrehzahl");
				break;
		case DREHZAHL:
				System.out.print("\tAnfrage: " + s + "\t\t\tTemperatur");
				break;
		case GESCHWINDIGKEIT:
				System.out.print("\tAnfrage: " + s + "\t\t\tGeschwindigkeit");
				break;	
		}
			System.out.println();
		
		os.print(s);
		os.print("\r\n");
		// Expect the modem to echo the command.
		if (!expect(s)) {
			System.err.println("WARNING: Modem did not echo command.");
		}
		// The modem sends an extra blank line by way of a prompt.
		// Here we read and discard it.

		String junk = is.readLine();

		String command = s;
		String result = junk;
		int richtig = -1;
		switch(MAP.get(s)) {
		case TEMPERATUR:
		     richtig = getTemperatur(command, result);
		     break;
		case DREHZAHL:
		     richtig = getDrehzahl(command, result);
		     break;
		case GESCHWINDIGKEIT:
		     richtig = getGeschwindigkeit(command, result);
		     break;
		}
		System.out.println("\tAntwort: " + junk + "\t\tRichtiger Wert: " + richtig);
		System.out.println();
	}

	/**
	 * Read a line, saving it in "response".
	 * 
	 * @return true if the expected String is contained in the response, false
	 *         if not.
	 */


	protected boolean expect(String exp) throws IOException {

		response = is.readLine();

		if (debug) {

		}
		return response.indexOf(exp) >= 0;
	}
}
 
hi shortyyyy

Einer von deinen Switch-Statements ist falsch^^
(case TEMPERATUR: .... "Drehzahl")

Aber nun mal zu deinem eigentlichen Problem:
Die Exception besagt, dass der String nicht die richtige Größe für den Substring-Befehl hat.
Die erste was du tun könntest, wäre einmal zu schauen was in den Variablen command und result steht bevor die Funktionen aufgerufen werden, in denen der Fehler passiert.
 
Zurück