kai-morich / SimpleUsbTerminal

Android terminal app for devices with a serial / UART interface connected with a USB-to-serial-converter
MIT License
529 stars 195 forks source link

Receiving data in sporadic manner after spn got converted into string #55

Closed hillyuyichu closed 1 year ago

hillyuyichu commented 1 year ago

I'm creating a new java class within the SimpleUSBTerminal app that reads the real time temperature data from my Arduino/its temperature sensor(Max 6675 K type). The terminal fragment class works fine and is able to display my temperature reading from Arduino. But when I made an almost identical copy of it, it started to send temperature data in pieces. For example, 30.50 degree. 3 arrived, then 0.50 arrived 2 seconds later.

Here's what I've changed:

    private void receive(ArrayDeque<byte[]> datas) {
        SpannableStringBuilder spn = new SpannableStringBuilder();
        for (byte[] data : datas) {
            if (hexEnabled) {
                spn.append(TextUtil.toHexString(data)).append('\n');
            } else {
                String msg = new String(data);
                if (newline.equals(TextUtil.newline_crlf) && msg.length() > 0) {
                    // don't show CR as ^M if directly before LF                          
                    msg = msg.replace(TextUtil.newline_crlf, TextUtil.newline_lf);
                    // special handling if CR and LF come in separate fragments
                    if (pendingNewline && msg.charAt(0) == '\n') {
                        if(spn.length() >= 2) {                                         
                            spn.delete(spn.length() - 2, spn.length());
                        } else {
                            Editable edt = receiveText.getEditableText();
                            if (edt != null && edt.length() >= 2)                         
                                edt.delete(edt.length() - 2, edt.length());
                        }
                    }
                    pendingNewline = msg.charAt(msg.length() - 1) == '\r';
                }
                spn.append(TextUtil.toCaretString(msg, newline.length() != 0));
            }
        }

              receiveText.setText(spn.toString());
         // receiveText.append(spn);

    }
kai-morich commented 1 year ago

it is normal to receive data in fragments, see https://github.com/mik3y/usb-serial-for-android/wiki/FAQ#user-content-When_reading_a_message_why_dont_all_bytes_arrive_at_the_same_time

hillyuyichu commented 1 year ago

The problem may not be the byte [] size, prefix length or read until '\n'.

I tried the solution in FAQ. I don't think that's my problem. I was able to use your original terminal just fine except until I decided to change append() to setText(). Because I want to extract a temp reading (eg. 27.83) from the data and update the data continuously.

Here's me implementing a new method called startTemperatureReading in lieu of your original receive(ArrayDeque<byte[]> datas):

1:

Private void startTemperatureReading(ArrayDeque<byte[]> datas){
          // Create a thread to read temperature data continuously

        Thread temperatureThread = new Thread(){
            @Override
            public void run() {

                String dataStr = "";
                String buffer = "";
                for (byte[] data : datas) {
                    try {
                        String dataUtf8 = new String(data, "UTF-8");
                        Log.i("temp thread", "Data received: " + dataUtf8);

                        buffer += dataUtf8;

                        int index;
                        while ((index = buffer.indexOf('\n')) != -1) {
                            dataStr = buffer.substring(0, index + 1).trim();
                            buffer = buffer.length() == index ? "" : buffer.substring(index + 1);
                        }
                    } catch (UnsupportedEncodingException e) {
                        Log.e("temp thread", "Error receiving USB data", e);
                    }

                    String finalDataStr = dataStr;
                    ((Activity) getContext()).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            temperatureTextView.setText(finalDataStr);

                        }
                    });
                }
            }
                };

        temperatureThread.start();
        }

The result of implementing this only gives 4 random digits( including the decimal) at a time. Sometimes, it gives 3 or 2 characters.

2:

private void startTemperatureReading(ArrayDeque<byte[]> datas) {
                for (byte[] data : datas) {
                    String temperatureData = new String(data);

                    //Use regular expressions to extract the temperature value
                    Pattern pattern = Pattern.compile("\\d+\\.\\d+");
                    Matcher matcher = pattern.matcher(temperatureData);

                    if (matcher.find()) {
                        String temperatureValue = matcher.group();
                        try {
                            double temperature = Double.parseDouble(temperatureValue);
                            // Use the temperature value as needed (e.g., display it in a TextView)
                            getActivity().runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    temperatureTextView.setText(String.valueOf(temperature));
                                }
                            });
                        } catch (NumberFormatException e) {
                            // Error parsing the temperature value
                            e.printStackTrace();
                        }
                    }
                }
            }

This one always misses the first and last digit. Say a 27.89 output data. It would only display 7.89 or 27.8 sometimes even 7.8

How would you go about this? Is this still a byte size problem?

hillyuyichu commented 1 year ago

it is normal to receive data in fragments, see https://github.com/mik3y/usb-serial-for-android/wiki/FAQ#user-content-When_reading_a_message_why_dont_all_bytes_arrive_at_the_same_time

Sorry forget to quote you in my last comment.