Byte hex80


#1

Hallo

Ein Messgerät sendet einen unsigned Byte mit dem Wert (hex80 =dec128 =bin1000 000)an meine App.

Da wir aber Vorzeichen behaftete Bytes in Java haben ist die Wertgrenze ja bei uns -128 bis 127. Das Problem wollte ich mit einer einfachen Rechnung umgehen.

mit einer signedByteToInteger Methode. In der Theorie funktioniert das auch einwandfrei.

Das Mysteriöse Problem ist nur, das genau dann wenn, das Gerät hex 80 sendet, dann empfängt die Android App “hex EF”, dec -17. Das sind dann die falschen Ausgangswert für die weitere Berechnung. Woran liegt das?


#2

trifft das hier zufällig zu?

Once I send the bytes with value of 128 to 255 by Bluetooth to Android then I see different bytes. I receive -17, -65, -67 instead of 128 to 255. But, it works with 0 to 127.

oder kannst du weitere Informationen liefern?
sind noch mehr Bytes vorhanden?

mit welcher nennbaren beteiligten Technik Daten gelesen/ gesendet?,
hast du beliebige Kontrolle über den Sender oder eine Alternative, für Tests, woher weißt du was gesendet wird?
funktionieren Werte > hex 80?


#3

Hi

Es wird sonst nur Text gesendet, das Problem ist auch lange Zeit nicht aufgefallen. Weil es nur für eine spezifische Situation gilt.
Also die Übermittlung funktioniert an allen anderen Stellen super, es sind einfach Log, Berichte die an die App gesendet werden. Bis auf diese eine Stelle, da sind es einfach nur eine Folge von Bytes mehr nicht.
Den Sender haben wir selbst gebaut und programmiert, durch ein Monitoring tool, kann man genau beobachten was er sendet. Wenn der Empfänger ein in c++ geschriebenes Programm ist, dann funktioniert es dort auch super.

Zum Link: Was für ein Zufall, es ist genau das Problem und wir nutzen auch genau diese Lib :smiley:

Ich lese mich da rein und meld mich wenn ich es lösen konnte

*** Edit ***

Alles klar es lag an der Lib. selbst, eine Änderung der Bibliothek hat das ganze behoben.

Genauer gesagt in Klasse SPPService:


  mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes()).sendToTarget();

Per default in read.getBytes() wird einfach der falsche Charset benutzt.


               mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes(StandardCharsets.US_ASCII)).sendToTarget();

Hat das Problem behoben.


#4

tja, da war es auf jeden Fall die richtige Entscheidung von dir,
dich an meine fortschrittlichen Suchmaschinenfähigkeiten zu wenden :wink:

‘android byte 128 239’ war die letztlich passende Suche,
und dafür musste ich erst lange lernen dass weder Hex-EF noch -17 (auch in Anführungszeichen, nicht als Suchausschluss) viel hilft, sondern der Gegenwert 239…


#5

Hallo, das Problem ist in etwa mein aktuelles. Da es hier noch recht übersichtlich ist, mache ich mal kein neuen Thread auf.

Mein Android empfängt Daten über Bluetooth (Messwerte, Rohformat), bei dem Versuch diese korrekt zu lesen/speichern drehe ich mich leider im Kreis.

Code 1:

  
                           int[] ret = new int[readBuf.length];
                            for (short i = 0; i < readBuf.length; i++)
                        {
                              ret** = (readBuf**&255);
                           }
 
 
                            String strIncom = new String(ret, 0, msg.arg1); // erstelle String aus Bytes Array
                            sb.append(strIncom);                                                // String anhängen
                            int endOfLineIndex;
                       
 
                            while ((endOfLineIndex = sb.indexOf("|0|")) >= 0) {                  // wenn end-of-line,
                                String sbprint;                                                 // extrahiere String
                                sbprint = sb.substring(0, endOfLineIndex);
                                sb.delete(0, sb.length());                                      // und löschen
 
                                try {
                                    File myFile = new File(path);
                                    myFile.createNewFile();
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
                                    OutputStreamWriter myOutWriter =
                                            new OutputStreamWriter(fOut);
                                    myOutWriter.append(sbprint);
                                    myOutWriter.close();
                                    fOut.close();

Ich hab versucht jedes Element in meinem Input-stream mit 0&FF zu
erweitern… die untere Hälfte des Wertebereichs ist alles richtig, aber
statt einer 0x80 erhalte ich dann eine: c2 80,

für 0x81 eine c2 81, für 0x82 c2 82, usw… Durch meine String-konvertierung läuft was falsch. Diese dient mir als Index um den Buffer richtig auszulesen.

Code 2:

 
                                try {
                                    File myFile = new File(path);
                                    myFile.createNewFile();
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
                                   
                                    fOut.write(readBuf);
                                    fOut.close();

Speichert die Werte richtig, dh. ich bekomme 0xFF aber der Buffer wird willkürlich gelesen, da der Index fehlt.

Es gelingt mir aber nicht diesen ohne Stringkovertierung richtig auszulesen…

Mein Ansatz findet sich in Code 3:

 
                            for (int i = 0; i < readBuf.length - 2; i++) {
                                if (readBuf** == '|' && readBuf[i+1] == '0' && readBuf[i+2] == '|') {
                                    int endePos = i;
                                    break;
                                }
                            }
 
                                try {
                                    File myFile = new File(path);
                                    myFile.createNewFile();
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
                             
                                    fOut.write(readBuf, 0, readBuf.endePos); //ist nicht...
                                    fOut.close();

Weiß jemand wie das richtig geht? mir, als Java-Neuling,gehen die Ideen aus… Danke im Voraus.

*** Edit ***

Sorry im Code 1 muss es heißen:

                    String strIncom = new String(ret, 0, msg.arg1);                 // erstelle String aus Bytes Array

[edit SlaterB: editiert]

Danke fürs Freischalten.


#6

edit:
erste Hälfte bis zu ############ für dich vielleicht nicht ganz nötig, editiere gleich noch was dazu, edit: zweite Hälfte nun auch da

erste Hälfte:

die API gibt es ja auf Github, auch als Quellcode,
kannst du beurteilen etwa welche Version du verwendest? könntest du den Code modifizieren und dann verwenden?


neues Issue 10 dort:


wohl von @ZickZack

seit 2 Monaten, seit Issue 9, sehe ich dort eine Änderung in der betroffenen Klasse

statt zuvor die wirklich falsche String-Umwandlung steht dort neuerdings, also bereits seit 2 Monaten

byte[] read = new byte[length];
System.arraycopy(data, 0, read, 0, length);
mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, length, -1, read).sendToTarget();

also gar keine interne Umwandlung mehr in String, sondern Weiterreichen als byte[]…
@ZickZack
kannst du dazu etwas sagen, wie passt das zu deinem

[QUOTE=ZickZack]
Alles klar es lag an der Lib. selbst, eine Änderung der Bibliothek hat das ganze behoben.

Genauer gesagt in Klasse SPPService:


  mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes()).sendToTarget();

Per default in read.getBytes() wird einfach der falsche Charset benutzt.


               mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes(StandardCharsets.US_ASCII)).sendToTarget();

Hat das Problem behoben.[/QUOTE]
wenn doch die API schon seit 2 Monate kein read.getBytes() mehr hat?

ob das Weiterreichen als byte[] gut oder schlecht ist kann ich kaum beurteilen,
Alternative wäre wohl der Code aus dem zweiten Posting im Issue 10-Link


wenn neueste API-Version nicht reicht (evtl. von @ZickZack was fertiges zu bekommen?)
und eigene Code-Eingriffe nicht möglich sind oder es nicht besser machen,
dann noch zwei Punkte:

einerseits Datensenden ändern/ vereinfachen, in


wurde genannt, womöglich Strings zu senden,
aber auf ‘Daten über Bluetooth (Messwerte, Rohformat)’ hast du vielleicht keinen Einfluss oder unpraktisch?

als letztes bliebe noch manuelle intensive Interpretation der Daten:
wenn ‘statt einer 0x80 erhalte ich dann eine: c2 80’ gilt, dann vielleicht nach c2 80 schauen unddies in 0x80 umwandeln usw.,
kann leicht unmöglich sein, falls auch c2 80 einzeln valide Werte sind

dann muss doch korrekte Übertragung her oder so einfache Daten übertragen werden dass die kaputte API ausreicht

##############

zweite Hälfte:

da die API seit 2 Monaten die bytes direkt durchschickt ist dazu vielleicht gar kein Problem vorhanden,
du sagst ja auch selber dass du den Fehler bei dir siehst

was ist bei String strIncom = new String(ret, 0, msg.arg1); das ‘msg.arg1’,
Anzahl der zu lesenden bytes?
weißt du um CharSets für Strings? teste doch mal das von Zickzack genannte
new String(ret, 0, msg.arg1, StandardCharsets.US_ASCII)

aber was lässt dich überhaupt vermuten, dass die Daten in String umzuwandeln sind? was stellen die Daten überhaupt dar?
allgemein keine empfehlenswerte Option für beliebige Daten,
was dann ja auch mehr oder weniger den Fehler in der API ausgelöst hat, um den es hier ursprünglich ging, der dich aber vielleicht gar nicht betrifft

was für Daten bekommst du in welchem genauen Format, warum willst du sie in String umwandeln, was genau erwartest du dann, was ist der Fehler?
‘statt einer 0x80 erhalte ich dann eine: c2 80’ ist etwas ungenau

oder mal anders gefragt: wie genau ist der gesuchte ‘Index’ formatiert, gib konkrete Beispiele zu den empfangenen Bytes, was du zum Auslesen planst, was schief geht,

zu deinem ‘Code 3’ hast du nichts negatives dazugeschrieben, funktioniert das schon? reicht das nicht?


#7

Hi slaterB,
Vielen Dank fuer deine ausführliche Antwort!!
Ich bin grad noch beschäftigt, werde mich aber nochmal melden. Wollte nur mal im Voraus danke sagen :slight_smile:


#8

ok fangen wir an, zunächst nochmal vielen Dank!

Bevor ich auf die Einzelheiten eingehe:

Für (StandardCharsets.US_ASCII)

erhalte ich: cannot resolve Symbol… was muss ich da importieren?

Danke!

*** Edit ***

Zwecks Übersicht und für die Nachwelt mal meine MainActivity.

mit 3 x /////////////////////////////////////////////////////////////// sind die betroffenen Stellen markiert.


package com.example.Musiktherapie;






import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Spinner;
import android.widget.Toast;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;


public class MainActivity extends Activity {
    private static final String TAG = "Musiktherapie";

    //Variablen setzen
    Button btnOn, btnOff;
    TextView txtArduino;
    Handler h;
    EditText dateipfad;
    boolean recording;
    final int RECIEVE_MESSAGE = 1;
    private BluetoothAdapter btAdapter = null;
    private BluetoothSocket btSocket = null;
    private StringBuilder sb = new StringBuilder();
    private ConnectedThread mConnectedThread;
    private Camera myCamera;
    private MyCameraSurfaceView myCameraSurfaceView;
    private MediaRecorder mediaRecorder;

    // SPP UUID Service
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private boolean is_connected = false;
    private static String address = "20:15:06:24:45:69";

    /**
     * Wird einmal aufgerufen wenn Activity startet
     */
    @Override

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        recording = false;
        setContentView(R.layout.activity_main);




        //Spinner inizialisieren für die G-Settings

        //liste mit items
        final List<String> list=new ArrayList<String>();
        list.add("G_Range 2");
        list.add("G_Range 4");
        list.add("G_Range 8");



        //spinner erstellen
        final Spinner G  =(Spinner) findViewById(R.id.spinner);


            //liste als adapter
            ArrayAdapter<String> adp = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
            adp.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            G.setAdapter(adp);


        G.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                mConnectedThread.write(String.valueOf(2*(G.getSelectedItemPosition())));
            }@Override
             public void onNothingSelected(AdapterView<?> parentView) {
                  // erst mal nicht wichtig
            }



        });





                ///////////Kameravorschau/////////////
                myCamera = getCameraInstance();

            myCameraSurfaceView=new MyCameraSurfaceView(this,myCamera);

            FrameLayout myCameraPreview = (FrameLayout) findViewById(R.id.videoview);
            myCameraPreview.addView(myCameraSurfaceView);

            btnOn=(Button) findViewById(R.id.btnOn);

            btnOff=(Button) findViewById(R.id.btnOff);

    dateipfad=(EditText)this.findViewById(R.id.dateipfad);


    Button btnOff = (Button) findViewById(R.id.btnOff);
    btnOff.setOnClickListener(new

    OnClickListener() {
        public void onClick (View v){
            mediaRecorder.stop();
            //mConnectedThread.write("3");
                    recording = false;
                    Toast.makeText(getBaseContext(),
                            "Messwerte gespeichert!",
                            Toast.LENGTH_SHORT).show();
                }
            }

            );






        h=new

            Handler() {
                public void handleMessage (android.os.Message msg){


                    switch (msg.what) {
                        case RECIEVE_MESSAGE:
                            byte[] readBuf = (byte[]) msg.obj;




                            int[] ret = new int[readBuf.length];
                            for (short i = 0; i < readBuf.length; i++)
                        {
                              ret** = ((readBuf**)&0xFF);

                           }
                            //for (int i = 0; i < readBuf.length - 2; i++) {
                              //  if (readBuf** == '|' && readBuf[i+1] == '0' && readBuf[i+2] == '|') {


                                //    int endePos = i;
                                  //  break;
                                //}
                            //}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                       String strIncom = new String(ret, 0, msg.arg1);                 // erstelle String aus Bytes Array
                            sb.append(strIncom);                                                // String anhängen
                            int endOfLineIndex;
                            String path = "sdcard/" + dateipfad.getText().toString() + ".txt";  //Environment.getExternalStorageDirectory().getPath()

                            while ((endOfLineIndex = sb.indexOf("|0|")) >= 0) {                  // wenn end-of-line,
                                String sbprint;                                                 // extrahiere String
                                sbprint = sb.substring(0, endOfLineIndex);
                                sb.delete(0, sb.length());                                      // und löschen

                                try {
                                    File myFile = new File(path);
                                    myFile.createNewFile();
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
                                   fOut.write(sbprint.getBytes());
                                    fOut.close();

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                                } catch (Exception e) {
                                    Toast.makeText(getBaseContext(), e.getMessage(),
                                            Toast.LENGTH_SHORT).show();
                                }
                            }
                            break;
                    }
                }

            }

            ;

            btAdapter=BluetoothAdapter.getDefaultAdapter();        // get Bluetooth adapter vom Smartphone

            checkBTState();


            btnOn.setOnClickListener(new

            OnClickListener() {
                public void onClick (View v){


                    if (recording) {                                 // Aufnahme stoppen und Kamera loslassen
                        mediaRecorder.stop();                       // Aufnahme stoppen
                        releaseMediaRecorder();                      // Mediarecorder Objekt loslassen

                    } else {

                        //Kamera loslassen bevor der MediaRecorder startet
                        releaseCamera();
                        if (!prepareMediaRecorder()) {
                            Toast.makeText(MainActivity.this,
                                    "Fail in prepareMediaRecorder()!
 - Ended -",
                                    Toast.LENGTH_LONG).show();
                        }

                        mediaRecorder.start();
                        recording = true;
                    }

                    mConnectedThread.write("1");


                    if (is_connected){
                        Toast.makeText(getBaseContext(), "Starte Messung", Toast.LENGTH_SHORT).show();




                    }





                }
            }

            );

        }



    private Camera getCameraInstance() {
// TODO Auto-generated method stub
        Camera c = null;
        try {
            c = Camera.open();                  // Kamera-Instanz öffnen
            c.setDisplayOrientation(90);
        } catch (Exception e) {
                                                // Kamera nicht verfügbar
        }
        return c;                               // gibt null aus wenn Kamera nicht verfügbar
    }


    private boolean prepareMediaRecorder() {
        myCamera = getCameraInstance();
        mediaRecorder = new MediaRecorder();

        myCamera.unlock();
        mediaRecorder.setCamera(myCamera);
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mediaRecorder.setAudioEncodingBitRate(128000);
        mediaRecorder.setAudioSamplingRate(48000);
        mediaRecorder.setVideoSize(1280,720);
        mediaRecorder.setVideoEncodingBitRate(12000000);
        mediaRecorder.setVideoFrameRate(30);
        mediaRecorder.setOutputFile("sdcard/" + dateipfad.getText().toString() + ".mp4");




        mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder().getSurface());
        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            releaseMediaRecorder();
            return false;
        }
        return true;
    }

    private void releaseMediaRecorder() {
        if (mediaRecorder != null) {
            mediaRecorder.reset();
            mediaRecorder.release();
            mediaRecorder = null;
            myCamera.lock();
        }
    }

    private void releaseCamera() {
        if (myCamera != null) {
            myCamera.release();
            myCamera = null;
        }
    }

    public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{

        private SurfaceHolder mHolder;
        private Camera mCamera;

        public MyCameraSurfaceView(Context context, Camera camera) {
            super(context);
            mCamera = camera;
            mHolder = getHolder();
            mHolder.addCallback(this);

        }


        public void surfaceChanged(SurfaceHolder holder, int format, int weight,
                                   int height) {
            if (mHolder.getSurface() == null){

                return;
            }


            try {
                mCamera.stopPreview();
            } catch (Exception e){
            }


            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();
            } catch (Exception e){
            }
        }

        public void surfaceCreated(SurfaceHolder holder) {

            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
            }
        }


        public void surfaceDestroyed(SurfaceHolder holder) {
            // TODO Auto-generated method stub
        }
    }

    private void checkBTState() { //*Bluetooth aktivivieren
        // Prüfe Bluetooth Unterstützung und prüfe ob eingeschalten
        if(btAdapter==null) {

            errorExit("Fatal Error", "Bluetooth not support");
        } else {
            if (btAdapter.isEnabled()) {
                Log.d(TAG, "...Bluetooth ON...");
            } else {
                //////Bluetooth einschalten//////
                BluetoothAdapter.getDefaultAdapter().enable();
            }
        }
    }

  private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
      if(Build.VERSION.SDK_INT >= 10){
          try {
              final Method  m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
              return (BluetoothSocket) m.invoke(device, MY_UUID);
          } catch (Exception e) {
              Log.e(TAG, "Could not create Insecure RFComm Connection",e);
          }
      }
      return  device.createRfcommSocketToServiceRecord(MY_UUID);
  }

  @Override
  public void onResume() {
    super.onResume();

    Log.d(TAG, "...onResume - try connect...");
    BluetoothDevice device = btAdapter.getRemoteDevice(address);

	try {
		btSocket = createBluetoothSocket(device);
	} catch (IOException e) {
		errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
	}

    btAdapter.cancelDiscovery();

    /////////////Verbindung aufbauen//////////
    Log.d(TAG, "...Connecting...");
    try {
      btSocket.connect();

        is_connected = true;
        ((TextView) findViewById(R.id.textView)).setText("Connect: " + address);
      Log.d(TAG, "....Connection ok...");
    } catch (IOException e) {
      try {
        btSocket.close();
      } catch (IOException e2) {
          is_connected = false;
        errorExit("Fatal Error", "In onResume()" + e2.getMessage() + ".");
      }
    }

    //////////////Datenstrom erstellen///////////////
    Log.d(TAG, "...Create Socket...");
    mConnectedThread = new ConnectedThread(btSocket);
    mConnectedThread.start();

  }

  @Override
  public void onPause() {
    super.onPause();
      releaseMediaRecorder();          // in der Pause mediarecorder loslassen
      releaseCamera();                 // und Kamera loslassen
    Log.d(TAG, "...In onPause()...");

    try     {
      btSocket.close();
    } catch (IOException e2) {
      errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
        //if (is_connected) {
      //  }
    }
  }



  private void errorExit(String title, String message){
    Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
    finish();
  }

//////Datenverbindung///////
  private class ConnectedThread extends Thread {
	    private final InputStream mmInStream;
	    private final OutputStream mmOutStream;

	    public ConnectedThread(BluetoothSocket socket) {
	        InputStream tmpIn = null;
	        OutputStream tmpOut = null;

	        try {
	            tmpIn = socket.getInputStream();
	            tmpOut = socket.getOutputStream();
	        } catch (IOException e) { }

	        mmInStream = tmpIn;
	        mmOutStream = tmpOut;
	    }

	    public void run() {
	        byte[] buffer = new byte[1024];  // Pufferspeicher für den Stream
	        int bytes; // ausgegebene Bytes von read()
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////7


	        //  InputStream lesen bis Fehler auftreten
	        while (true) {
	        	try {
	                // Lese InputStream
	                bytes = mmInStream.read(buffer);		// Erhalte Anzahl der Bytes und der Daten in "buffer"
                    h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();		// Sende zum Handler
	            } catch (IOException e) {
	                break;
	            }
	        }
	    }

	    /* aus der Main activity aufrufen für das Senden zum msp */
	    public void write(String message) {
	    	//Log.d(TAG, "...Data to send: " + message + "...");
	    	byte[] msgBuffer = message.getBytes();
	    	try {
	            mmOutStream.write(msgBuffer);
	        } catch (IOException e) {
	         //   Log.d(TAG, "...Error data send: " + e.getMessage() + "...");
	          }
	    }
	}




}

#9

import java.nio.charset.StandardCharsets;
ab Java 1.7?

hast du eine IDE wie Eclipse mit automatisch organisierten Import?
Grundlagen wären empfehlenswert


#10

ich programmier mit Android Studio. Der weigert sich aber das zu importieren.


#11

Java hab ich installiert 1.8.0_77


#12

etwas verrücktes wie ‘Android Studio’ zu nehmen oder ‘import android.app.Activity;’, das kann für sich böse enden,
vielleicht nur ein reduziertes Java für Smartphones in Verwendung, wo dann das nicht zur Verfügung steht,

Alternative wäre, von normalen IDEs und unbelasteten Hello World-Programm Dinge die unklar sind anzugehen,
StandardCharsets ist in der API
https://docs.oracle.com/javase/7/docs/api/java/nio/charset/StandardCharsets.html
wie ‘java.nio.ByteBuffer’ oder ArrayList oder sonst was einfaches,
jede API-Klasse muss importierbar sein, sonst halt was auch immer für ein Problem vorliegend, alles löschen,
neuer Computer, neu installieren…

wie gesagt vielleicht auch gar kein Thema für dich, nicht in der zweiten Hälfte :wink:

‘weigert sich aber das zu importieren’ ist auch keine besonders korrekte Fehlermeldung


#13

Sorry dass ich mich so sporadisch melde, arbeite an mehren Baustellen gleichzeitig :slight_smile:

Das importieren hat geklappt, sdk Version wurde auf 19 aktualisiert.

Behoben hat das mein Problem leider nicht.

So was wird überhaupt aufgenommen und was hat es mit dem |0| auf sich.

Gesendet werden an das Handy Sensor-Messwerte, zusätzlich zu Beginn die gewählten Einstellungen, in Form von: " Sie messen im 2G Bereich(String)". Das wird alles richtig gesendet und gespeichert.

Danach geht los. |0| markiert das erste Paket, danach folgen ca. 30 Werte, dann |1| dann wieder 30 Werte usw… , alles richtig.

sobald das Startpaket |7f| überschreitet, steht dann da wenn ich es mit >>ret<< mache: 2c 0x80, statt nur 0x80. Für 0x81 eine 2c 81…

Das gleiche Verhalten zeigt sich in den Messwerten die überhalb des oberen halben Wertebereichs liegen.

Wobei wenn ich statt mit >>ret<< direkt mit >>readBuf<< weiter arbeite (siehe 1.Code)

sind alle Werte über 0x80 gleich undzwar: c3 bf. (Sie messen XY immer noch korrekt).

Bei Code 2, habe ich die 0xff korrekt da, nur:

Da liest und/oder speichert das Handy den Buffer willkürlich und so wie ich das verstanden habe muss man beim Auslesen einen Index, Längenintervall o.ä. angeben damit er die Daten richtig liest, dh. alles einmal, nichts doppelt und chronologisch richtig.

Code 3 ist nichts vollständiges, da ich nicht weiter wusste wie die richtigen Daten(-abschnitte) extrahieren soll.

Danke vielmals für deine bisherigen Informationen, das ist für mich ein wichtiger Anhaltspunkt :slight_smile:

Am besten wäre ein Source-Code für einen Bluetooth-Datenlogger wo ich mir was abschauen könnte.


#14

erste Hälfte wiederum evtl. uninteressanter als zweite:

Leute die es kennen gibt es wohl weniger als Sand am Meer, etwa @ZickZack vielleicht, der sich aber im Moment nicht meldet,
oder auch du selber, unregistriert, vielleicht zu allen anderen Zeiten nicht da um anderen zu helfen :wink:

die die da sind, kennen nicht unbedingt die API genau


wie bist du überhaupt zu diesem Tool gekommen, was würdest du machen wenn es das nicht gäbe?
wo immer es herkommt, gab es da kein Beispiel usw. dazu?

im GitHub ist ein Beispiel genannt


aber da ist wenig zu sehen…, anscheinend getString() aus aus AppCompatActivity oder höher für Empfang genutzt?


ob passend oder nicht, mit bestimmend für das Thema hier am Anfang und den beiden Issues in Github



geht es um die Klasse SPPService in der API

mit ConnectedThread, Handler,
Codezeile mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, length, -1, read).sendToTarget();

da ist es für mich verwirrend, warum du anscheinend in deinem Code, in der MainActivity, auch ConnectedThread, Handler,
und Codezeile h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Sende zum Handler
hast…

fällt dir dazu etwas zu sagen ein?
hast du den Code irgendwo kopiert, unter welchen Anleitungen? oder wie sonst kommst du auf die Idee, etwas wie sendToTarget() einzutippen,
darauf kommt ja nicht von alleine, was ist der Grundplan, der ja irgendwie vorhanden sein muss?

##########

zweite Hälfte:

eine solche Angabe ist ungünstig, weil nichts genaues verraten wird,
ist ‘|7f|’ bzw. ein drüber also ‘|80|’ eine Vermutung des Verhaltens des Senders oder kommt das auch schon im Programm an?
meinst du damit eigentlich ein byte oder drei Bytes?

‘steht dann’ kann ungenauer nicht sein, bist du mit der Endausgabe in der Fileoutputstream-Datei auf der Festplatte (oder wo auch immer) unzufrieden, was auch nur an verwendeten Datei-Leser liegen kann,
oder stellst du das schon irgendwo im Programm fest?
es gibt mehrere byte-Arrays im Programm, mehrere Positionen wo bytes Schritt um Schritt umgewandelt werden, da wäre Genauigkeit so wichtig…,
welche konkreten Daten liegen je Position vor, werden in was umgewandelt, wo unzufrieden?

wobei: hier ein Test der deinem Satz nahe kommt:

    public static void main(String[] args)   {
        byte[] readBuf = new byte[]          {-128};

        int[] ret = new int[readBuf.length];
        for (short i = 0; i < readBuf.length; i++)    {
            ret** = ((readBuf**) & 0xFF);
        }
        System.out.println("readBuf: " + Arrays.toString(readBuf));
        System.out.println("ret    : " + Arrays.toString(ret));
        String st = new String(ret, 0, ret.length);
        System.out.println(st.length() + " - " + st);
        System.out.println(Arrays.toString(st.getBytes()));
    }
}

Ausgabe:

readBuf: [-128]
ret    : [128]
1 - €
[-62, -128]

aus einem byte -128 = 0x80 wird ein String mit den Bytes -62 = c1 + -128 = 0x80

warum willst du die -128 überhaupt umwandeln, was genau erhoffst du dir im String auszulesen?
ich vermute dass das hier nicht geht, ein Ansatz a la
if (readBuf** == '|' && readBuf[i+1] == '0' && readBuf[i+2] == '|')
klingt vielversprechender, je nachdem ob die ‘|’ in einzelnen Bytes da sind, welche Bytes genau, das musst du alles feststellen

wie hoch wird eigentlich gezählt wenn das mittlere Byte eine Nummerierung ist?
du sagst |0| bis |0x80| geht, das ist ja schon die Hälfte der Zahlen, die in ein Byte passen, wie wird das 256. Paket angefangen, mit zwei Bytes für Zählung?
kann ja dann irgendwann auch sein, dass das zweite Zähl-Byte just den Wert von ‘|’ hat, auf sowas aufzupassen…

das wird wohl kein anderer für dich (noch genauer als ich jetzt schon) machen, und ob du dafür der richtige bist? :wink:
(ich bin in diesem Forum-Thema irgendwie recht frech, sorry falls störend)

wichtig ist wahrscheinlich auch, die Nutzdaten dahinter dann direkt als bytes in eine Datei zu schreiben,
Umwandlung in String und mit getBytes() die Bytes wieder raus ist immer als problematisch anzunehmen,
es sieht ganz nach byte-Schnipseln aus, für mich


das ursprüngliche Problem des Threads wiederum evtl. gar kein Thema bei dir,
womöglich die API ja auch schon seit 2 Monaten korrekt, und dann verwendest du womöglich nicht einmal SPPService, weil selber ähnlichen Code…,
lauter (Wo-)Möglichkeiten


#15

Hallo SlaterB,

nochmal vielen, vielen Dank für deine Mühe. Irgendwie will bei mir die Zitier-funktion nicht, deshalb zitiere ich per “Hand”.

wie bist du überhaupt zu diesem Tool gekommen, was würdest du machen wenn es das nicht gäbe?

Es gab eine “Vorarbeit” die jedoch sehr unstrukturiert ist. Ich arbeite mich ja auch noch ein :slight_smile: Was mein Plan wäre ist wenn’s nicht anders klappt, erst mal eine App zu proggen die nur Bluetoothdaten speichert, meine App macht noch einiges mehr. Ich denke ich werde es auch als Übung machen, wollte nur ein Projekt abschließen, und es hat eben nur dieses eine Detail gefehlt.

wo immer es herkommt, gab es da kein Beispiel usw. dazu?

Tutorials und AndroidStudio sind meine Quellen…

ist ‘|7f|’ bzw. ein drüber also ‘|80|’ eine Vermutung des Verhaltens des Senders oder kommt das auch schon im Programm an?

7f ist die höchste Zahl in hex-format die korrekt dargestellt wird auf der SD-Karte.
Der Sender macht alles richtig, denn auf einem Terminal erscheint alles korrekt. Die Werte werden gesendet in Roh-Format(binär) wie Sie im Register ausgelesen werden.

meinst du damit eigentlich ein byte oder drei Bytes?
drei.

‘steht dann’ kann ungenauer nicht sein,

Sry, wenn die Datei auf der SD-Karte gelesen wird. :slight_smile:
Die Werte werden ja gespeichert. Deswegen konnte ich lange nicht ausschließen ob das Speichern oder das Lesen falsch war.

es gibt mehrere byte-Arrays im Programm, mehrere Positionen wo bytes Schritt um Schritt umgewandelt werden, da wäre Genauigkeit so wichtig…,
welche konkreten Daten liegen je Position vor, werden in was umgewandelt, wo unzufrieden?

Eine Umwandlung brauche ich nicht. Es würde reichen wenn die Roh-Werte den Weg auf die SD-Karte finden. Wenn der Index zu ersetzen ist…
Aber wenn etwas falsch gemacht wird, warum stimmt sonst alles?
Und ausgerechnet ab 127 läuft es falsch. Muss dann wohl am unsigned liegen. Aber selbst wenn, wie kommt man dann auf eine C2 80, ein Minuszeichen ist doch anders kodiert?

warum willst du die -128 überhaupt umwandeln, was genau erhoffst du dir im String auszulesen?

sry, wenn ich mich nicht klar ausgedrückt hatte. Ich möchte sie nicht umwandeln. Mein Wertebereich geht von 0-255, also unsigned, so will ich es auch speichern :slight_smile:

Warum sie trotzdem gewandelt sind ist der Index… den ich nicht-gewandelt im Code 3 hab versucht zu ersetzen. Ich bin ein Java-Neuling, denke immer an Pointer…^^

Da ohne Wandlung die Werte korrekte sind aber auf der SD-Karte Ihre Reihenfolge nicht einhalten und sich manche mehrmals hintereinander vordrängeln.

Bestimmt ist die Lösung eine einfache… Ich möchte einfach das Array/Byte-Steram wie es empfangen wird auf die SD-Karte legen. Mein Programm versteht aber nicht, dass sagen wir wenn das Array 10 Byte lang ist, diese gespeichert werden sollen, dann die nächsten 10 Byte, und nicht irgendwas und auch nicht dieselben 10 Byte nochmal. Darum der Index von |0| bis |0|, String extrahieren, Speichern Löschen, nächster String…

Jetzt, beim ausformulieren meines Problems merke ich, dass es sicher nicht so schwer ist. Ich wusste nur nicht welchen Weg ich gehen sollte.

wie hoch wird eigentlich gezählt wenn das mittlere Byte eine Nummerierung ist?

255, also bis zum Überlauf und dann wieder von vorne :slight_smile:

du sagst |0| bis |0x80| geht, das ist ja schon die Hälfte der Zahlen, die in ein Byte passen

genau und die andere Hälfte soll auch noch stimmen.

An der Position wo ich nur ein Byte stehen haben müsste, habe ich auf der SD-Karte für 0x80 zwei Bytes: 0xc2 0x80, das C2-Byte soll verschwinden. Die gehören irgendwie zusammen. Wenn man um 1 immer erhöht folgt: C2 81… bis C2 bf und dann passiert: C3 80; C3 81…

kann ja dann irgendwann auch sein, dass das zweite Zähl-Byte just den Wert von ‘|’ hat, auf sowas aufzupassen…

Das macht nichts. Der Index setzt sich aus 3 bytes zusammen. Der Start vom Paket ist eben mit diesen 3 Bytes gekennzeichnet: |Paketzahl|. Dadurch kann geprüft werden, ob alle Pakete richtig ankommen und selbst wenn Werte dem Zeichen “|” entsprechen, kennt man ja zusätzlich die Anzahl der Werte pro Paket und kann diese dann einem Messwert zuordnen. Natürlich funktioniert das nicht mehr so einfach, wenn sich plötzlich zwei Bytes einschleusen C2 80.

Und sollten wirklich 3 Bytes zufällig den Messwerten |0| entsprechen, wird halt einmal ein kürzerer String extrahiert. Aber ich werde es dann mit Arrays probieren ohne Index.

das wird wohl kein anderer für dich (noch genauer als ich jetzt schon) machen

Das erwarte ich doch gar nicht :slight_smile: Ich bin dir aber dankbar.

Zu allen deinen Vorschlägen (auch in deinen vorherigen Posts) melde ich mich, wenn ich es mal verinnerlicht habe. Es hat mir schon sehr geholfen.

Vielen Dank.


#16

das dürfte ziemlich sicher von der Umwandlung in String kommen, die aktuelle zumindest,

ob es eine korrekte sinnvolle Umwandlung in einer Zeile gibt, mag ich mal nicht völlig ausschließen,
weil ich die Daten immer noch nicht ganz verstehe, aber bezweifle es

also die bytes direkt als bytes schreiben, bleibt nur die Frage nach dem Index

vage vage,
geht es darum, dass vorherigen Nachrichten nochmal gespeichert werden oder willst du aus einer aktuellen Nachricht nur Teile speichern?

Code 3 von Anfang ist wohl der richtige Weg, wie schon mal genannt,
jetzt sehe ich dort gerade ein paar einfache Fehler, die zumindest kann ich korrigieren:

int endePos = 0; // Variable vor der Schleife deklarieren
for (int i = 0; i < readBuf.length - 2; i++) {
  if (readBuf** == '|' && readBuf[i+1] == '0' && readBuf[i+2] == '|') { 
  // findet ja nur |0|, besser nur nach den || suchen, egal was bei i+1 steht

                endePos = i;
                break;
  }
}
     
try {
   File myFile = new File(path);
   myFile.createNewFile();
   FileOutputStream fOut = new FileOutputStream(myFile, true);
                                 
    fOut.write(readBuf, 0, endePos); // nicht readBuf.endePos..

#17

Sorry für das ganze Wirrwarr.

Also der relevante Code auf den es sich nur bezieht ist folgender (while schleife weg; ohne Stringbuilder also auch ohne Index).

ich versuch diesmal konkret zu sein.

switch (msg.what) {
                        case RECIEVE_MESSAGE:
                            byte[] readBuf = (byte[]) msg.obj;



String path = "sdcard/" + dateipfad.getText().toString() + ".txt";

                            try {


                                    File myFile = new File(path);
                                    myFile.createNewFile();
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
                                   fOut.write(readBuf, 0,readBuf.length);
);
                                    fOut.close();
}

Ziel: Wenn er was empfängt, soll das was empfangen wird gespeichert (einmal) und nur dann.

Bisher: Er speichert ca. 20 werte, dann kommen ca 100 Nuller, dann speicher er die gleichen 20 Werte nochmal, dann wieder 100 Nuller, dann speichert er die nächsten folgenden 20 Werte.

Was tun? Buffer verkleinern, for schleife…?

*** Edit ***

Mist, tschuldigung da ist ein }, zuviel, ich sollte mich wohl mal anmelden, dann kann ich auch bearbeiten?

*** Edit ***

Auf jeden Fall kannst du mir jetzt folgen :slight_smile:

Warum /oder wird nicht der Empfangspuffer beim auslesen Automatisch gelöscht, wie zB ein Register am Mikrocontroller.

Das Problem bei deinem Code ist, so wie ich das beurteilen kann, dass das for dazu führt dass der Index einmal erkannt wird.

Folglich habe ich ein Paket auf dem Speicher. Nun muss das nächste Paket ab da wo der Index gesetzt wurde bis zum nächsten Index gelegt werden.

ich habe jetzt mal da wir nicht da Strings suchen in HEX formatiert, den Index |0| =if (readBuf** == 0x7c && readBuf[i + 1] == 0x30 && readBuf[i + 2] == 0x7c)

geändert.

Die endePos ist bei mir POS1, nun soll er immer von der POS1 zu POS2 beschreiben. Diese müssen sich fortlaufend aktualisieren.

Meine Idee wäre es jetzt POS1 um die Anzahl der Werte(momentan:100) die mir bekannt sich zu erweitern = POS2.

im Nächsten Schritt müsste für POS2 wieder zu POS1 werden…

Die Index-Aktualisierung sollte dennoch erfolgen, falls ein Wert wegen kurz auftretender Störung nicht empfangen wurde.

Denke sowas in die Richtig ist der richtige Weg, bisher habe ich:


 case RECIEVE_MESSAGE:
                            byte[] readBuf = (byte[]) msg.obj;



                                   int POS1=0;

                            for (int i = 0; i < readBuf.length - 2; i++) {
                                if (readBuf** == 0x7c && readBuf[i + 1] == 0x30 && readBuf[i + 2] == 0x7c) {


                                    POS1 = i;
                                    break;
                                }
                            }
                            String path = "sdcard/" + dateipfad.getText().toString() + ".txt";

                            try {
                                    int POS2 = POS1+100;

                                    File myFile = new File(path);
                                    myFile.createNewFile();
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
                                   fOut.write(readBuf, POS1, POS2);
                                    fOut.close();


Danke, dass du mich nicht so schnell aufgibst :slight_smile:


#18

RECIEVE ist falsch benannt,

was die Lage ist ist weiterhin unklar, immer wieder dasselbe: du musst sagen welche Daten kommen,
was genau alles passiert

zunächst:
löscht jemand die Datei vor dem Anfang des Programms bzw. ist das wichtig?
FileOutputStream fOut = new FileOutputStream(myFile, true);
schreibt ans Ende der vorhandenen Dabei,
innerhalb des Programms sicher richtig, damit vorheriges nicht gelöscht wird,

wenn immer wieder mit den gleichen Daten Programm neu begonnen, dann würde sich freilich gleiches sammeln


danach:
wieviele Nachrichten gibt es?,
aus was genau besteht Nachricht 1, wieviele bytes, wieviele Werte, wieviele ‘Nuller’, was immer das bedeuten soll,
wie sieht die Datei (bzw. der neu gespeicherte Anteil) aus nachdem Nachricht 1 gespeichert wurde?
etwa dahinter Programmabbruch bewirken und anschauen,

wurde genau der Inhalt von Nachricht 1 korrekt gespeichert?

danach Nachricht 2, wieder genau zu sagen aus was sie besteht,
und was genau ist danach der Inhalt der Datei, nicht genau Nachricht 1 und dahinter Nachricht 2?
sondern was genau ist falsch, ist Nachricht 1 genau doppelt abgelegt oder was sonst das Problem?

‘irgendwo irgendwelche Nuller’, das ist keine Aussage…

edit:
0 in Datei kann leicht davon kommen, dass der unbelegte Rest eines byte-Arrays mitgespeichert wird,
bei fOut.write(readBuf, 0,readBuf.length); ja auch keine Kunst, nun fehlt der End-Index,
das wusstest du ja schon selber, keine echte Frage,

msg.arg1 wie in String strIncom = new String(ret, 0, msg.arg1);
hilft vielleicht zu erkennen, wieviel vom Array belegt ist
fOut.write(readBuf, 0,msg.arg1);
schon die Lösung aller Probleme?..

ich will mal auch Geheimnisse belassen, machen ja alles interessanter :wink:
aber gut raten ist erlaubt


#19

Also die Lösung wäre doch wenn der endePos sich ständig aktualisiert und

speichern wäre:

fOut.write(readBuf,endePos , endePos+100);// oder würde er die Daten dann überschreiben?


#20

hast du fOut.write(readBuf, 0,msg.arg1); schon getestet, ohne weiteres besprechen zu müssen?

zu

gäbe es sonst nur wieder viele neue Fragen,
was sollte überschrieben werden und wieso diese Vermutung?
was ist endePos, was steht davor in readBuf, wieso nicht zu speichern, wieso nur genau bis +100 dahinter speichern,

außerdem wieder komplette Beispiel-Daten mit Länge, mit endePos und mit Ergebnis in Datei wünschenswert