Search code examples
androiduartbuffering

Data From Serial Port keeps Buffering (Android Device cannot recognize it as a Data)


A question regarding the above title Why does my data transferred via serial port keeps on buffering? The android cannot recognize the data as a data. It cannot write the data received and transferred to the tag on the android device

This is the sendFileToTag function:

 public boolean sendFileToTag(Tag detectedTag, int sectorOrPage) {
        try {
            // Give the exact filePath
            String filePath = "/storage/self/primary/Upload_in_NFC.txt";

            // Read the file data
            String fileData = readFileAsString(filePath);

            // Encode the file data into an NDEF message
            byte[] ndefData = encodeNdefData(fileData);

            // Construct the NFC_Write command
            byte[] nfcWriteCommand = new byte[]{
                    (byte) 0xAA,  // Start byte
                    0x00,         // Length (variable, depends on the data being sent)
                    0x2C,         // Command byte for NFC_Write (0x94)
                    (byte) sectorOrPage, // Sector/Page (replace this with the appropriate sector or page number)
                    (byte) (ndefData.length + 1), // Length of NDEF data
                    0x01          // Start of NDEF data
                    // NDEF data goes here
                    // You may need to convert the fileData to bytes and place it here
            };

            // Write the NFC_Write command to the tag
            byte[] responseData = sendNFCCommand(detectedTag, nfcWriteCommand);

            // Check the response for errors
            if (responseData != null && responseData.length > 0 && responseData[0] == (byte) 0x00) {
                // Write successful
                byte[] cardNumber = Arrays.copyOfRange(responseData, 1, responseData.length);
                System.out.println("File data written to NFC tag");
                System.out.println("Card Number: " + asciiToHex(new String(cardNumber, StandardCharsets.US_ASCII)));
                return true;
            } else {
                // Handle the case where there was an error in the response
                showToast("NFC Write Error");
            }
        } catch (IOException e) {
            // Handle file reading error
            e.printStackTrace();
        }
        return false;
    }

This is the serial port configuration:

   // Find and open the USB serial port
        UsbSerialPort serialPort = findSerialPort(); // Implement the method to find the appropriate serial port

        try {
            // Open the serial port and configure parameters
            serialPort.open(usbManager.openDevice(serialPort.getDriver().getDevice()));
            // Configure parameters
            serialPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

            // Create a buffer to read the data
            byte[] buffer = new byte[1024];
            int totalBytesRead = 0;
            int MAX_DATA_SIZE = 1024; // Define your maximum data size here


            // Read data from the serial port
            while (true) {
                int bytesRead = serialPort.read(buffer, 1000); // Adjust the timeout value as needed

                // Convert the received bytes to a string
                if (bytesRead > 0) {
                    // Append the received bytes to the data
                    dataFromSerial += new String(buffer, 0, bytesRead);
                    totalBytesRead += bytesRead;


                    // Check for termination condition or end of transmission
                    if (dataFromSerial.contains("terminator")) {
                        break; // Exit the loop if the terminator is found
                    }

                    // Check for maximum data size or other conditions
                    if (totalBytesRead >= MAX_DATA_SIZE) {
                        break; // Exit the loop if maximum data size is reached
                    }
                } else {
                    // No more data to read
                    break;
                }
            }

This is the writeDataToFile:

   public void writeDataToFile(File directory, NdefMessage ndefMessage) {
        try {
            if (directory != null) {
                File file = new File(directory, "nfc_data.txt");
                try (FileOutputStream fos = new FileOutputStream(file)) {
                    // Process each NDEF record
                    if (ndefMessage != null) {
                        NdefRecord[] records = ndefMessage.getRecords();
                        for (NdefRecord record : records) {
                            // Assuming the record contains text data
                            if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN &&
                                    Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) {
                                // Decode the payload data
                                String dataFromNdef = new String(record.getPayload(), StandardCharsets.UTF_8);
                                // Write the NDEF data to the file
                                fos.write(("NDEF Data: " + dataFromNdef + "\n").getBytes(StandardCharsets.UTF_8));
                            }
                        }
                    }
                    Log.d("FileIO", "NFC Data written to file: " + file.getAbsolutePath());
                } catch (IOException e) {
                    Log.e("FileIO", "Error writing to file: " + e.getMessage());
                }
            } else {
                Log.e("FileIO", "Directory is null, cannot write to file.");
            }
        } catch (Exception e) {
            Log.e("FileIO", "Error: " + e.getMessage());
        }
    }

Solution

  • You have 2 problems here sendFileToTag is not receiving the complete NDEF data at once and incomplete data being used for writing to the tag.


    Solution to this is you should handle buffered data and send data length upfront.

    Steps to follow :

    1. Read file data and encoding NDEF

    2. Add data length to the beginning of nfcWriteCommand

    3. Open serial port & create a buffer to accumulate data

    4. Read data from the serial port in a loop

    5. Process accumulated data once totalBytesRead reaches dataLength

    6. Process accumulated data to construct NDEF message

    7. Writing to tag and handling response

    public boolean sendFileToTag(Tag detectedTag, int sectorOrPage) {
        try {
            // old code
    
            // Add data length to nfcWriteCommand
            int dataLength = ndefData.length;
            nfcWriteCommand[1] = (byte) (dataLength & 0xFF); // Lower byte of data length
            nfcWriteCommand[2] = (byte) ((dataLength >> 8) & 0xFF); // Upper byte of data length
    
            // old code
    
            // initilise buffer 
            byte[] buffer = new byte[1024];
            int totalBytesRead = 0;
    
            // Read data 
            while (true) {
                int bytesRead = serialPort.read(buffer, 0, buffer.length);
                if (bytesRead > 0) {
                    totalBytesRead += bytesRead;
                    // process data when totalBytesRead reaches dataLength
                    if (totalBytesRead == dataLength) {
                        // construct NDEF message
                        // ...
                        break;
                    }
                } else {
                    break;
                }
            }
    
            // ... writing to tag and handling response)
        } catch (IOException e) {
    
        }
        return false;
    }
    

    Read this for more information https://developer.android.com/develop/connectivity/nfc/advanced-nfc#read-write

    and topics like

    • Serial communication buffering

    • Handling buffered data in Android

    • NDEF message construction

    • Reading data in serial loop