【问题标题】:Understanding bluetooth rfcoom raw data了解蓝牙 rfcoom 原始数据
【发布时间】:2016-01-11 17:01:41
【问题描述】:

我正在尝试构建一个使用 rfcomm 读取通过蓝牙服务发送的信息的应用程序。 该设备是硬度计(HT-6510A),不幸的是找不到设备数据格式的规格我遇到了一个奇怪的问题,我必须了解如何阅读这些信息。

01-11 17:47:28.940 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:29.581 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:30.211 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:30.872 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:31.513 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:32.143 11862-13447/joinstore.it.testhardness V/result: ��T
01-11 17:47:32.794 11862-13447/joinstore.it.testhardness V/result: ��T

这是我从设备收到的数据,我认为在稳定 rfcomm 连接后仅使用此线程的实现没有问题。

    //After connection, handle data transfer
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

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

            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
//            readAndPublishRaw();
            readAndPublishString();
            Log.v("result", "Reading data ended.");
            setStatusText(-1);
        }

        void readAndPublishRaw(){
            byte[] buffer = new byte[1024];  // buffer store for the stream
            int bytes; // bytes returned from read()
            Log.v("result", "Start reading...");
            // Keep listening to the InputStream until an exception occurs
            while (true) {
                try {
                    // Read from the InputStream
                    bytes = mmInStream.read(buffer);
                    // Send the obtained bytes to the UI activity
                    Log.v("result", bytes + "");
                } catch (IOException e) {
                    break;
                }
            }
        }

        void readAndPublishString(){
            //String method, not useful in this case?
            try {
                BufferedReader r = new BufferedReader(new InputStreamReader(mmInStream));
                StringBuilder total = new StringBuilder();
                String line;
                Log.v("result", "Start reading...");
                while ((line = r.readLine()) != null) {
                    total.append(line);
                    Log.v("result", line);
                }
                Log.v("result", total.toString());
                //TODO publish read string to the view
            } catch (Exception e) {
                //
                try {
                    mmSocket.close();
                }catch (Exception ex){}
                Log.v(TAG, "exception reading data from service");
            }
        }

        /* Call this from the main activity to send data to the remote device */
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) {
            }
        }

        /* Call this from the main activity to shutdown the connection */
        public void cancel() {
            try {
                mmSocket.close();
                setStatusText(-1);
            } catch (IOException e) {
            }
        }
    }

你们能给我有关如何正确解析这些原始数据的任何信息吗?我想我应该有一个浮点值流,但我只是这些随机的东西。

【问题讨论】:

  • “不幸的是,无法找到有关设备数据格式的规范” - 您希望我们在不透露设备是什么的情况下为您提供帮助?!
  • “我想我应该有一个浮点值流”——很可能就是这样。但是,您知道通过蓝牙您只能获得 bytes 流。您必须查看那些 bytes 以了解这些值是如何编码的。简单地将字节“转换”为字符串并没有任何帮助。至少给我们一些 raw 格式的示例消息,即字节;也包括每条消息的长度
  • 我已经用设备名称更新了问题。现在我使用函数 readAndPublishRaw 一个接一个地获取字节,您知道获取此信息的更好方法吗?
  • 也可以考虑将问题移至reverseengineering.stackexchange.com
  • “我一个接一个地得到字节” - 注意InputStream.read(byte[] buffer) 将接收到的数据放入给定的缓冲区。 InputStream.read() 一个接一个地返回。但是,无论如何,一次将一条消息读入byte[] 是您想要的。

标签: android bluetooth rfcomm bluetooth-socket


【解决方案1】:

关于如何首先获得一些可用日志输出的建议:

    void readAndPublishRaw(){
        byte[] buffer = new byte[1024];  // buffer store for the stream
        int bytes; // bytes returned from read()
        Log.v("result", "Start reading...");
        // Keep listening to the InputStream until an exception occurs
        while (true) {
            try {
                // Read from the InputStream
                bytes = mmInStream.read(buffer);
                // Send the obtained bytes to the UI activity

              final StringBuilder sb = new StringBuilder();
              sb.append("Received ").append(bytes).append(" bytes: ");
              for ( int i = 0; i < bytes; i++ ) {
                sb.append( Integer.toHexString(((int)buffer[i]) & 0xff) ).append(", ");
              }

              Log.v("result", sb.toString());
            } catch (IOException e) {
                break;
            }
        }
    }

下一步应该是校准数据,即记下哪个输入/显示值会产生什么原始数据。从那里,您可能无法推断出实际的编码。

除了数据中的实际测量值之外,您的设备可能包含也可能不包含其他信息,例如指示电池电量低。必须将其分解才能获得原始测量值。

如果一个数据值包含多个字节,则需要确定字节顺序(小端或大端)。

小型设备的浮点数据通常以定点表示。有时,尤其是。如果也需要负数,则添加偏移量,以便

realValue = rawValue * a + c

如果你发现 ac 你很好。因此,一旦您从上面完成的校准中只能关联两个不同的realValues 和对应的rawValues,您就有足够的数据来求解ac 的方程。

具有更多“冲击力”的设备,例如嵌入式 linux 设备,也可以使用常规的IEEE floating point data。 - 并不是说​​小型嵌入式设备不能使用 IEEE,而是浮点数通常超出了要求,而且浮点仿真代码的复杂性(内存和 CPU)更高。

【讨论】:

    猜你喜欢
    • 2022-07-08
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 2021-12-27
    • 2018-06-30
    • 2015-03-08
    相关资源
    最近更新 更多