unity-game-engineserial-portnfc

Communication with serial port "/dev/ttyS3" in Unity


I'm trying to establish communication with my NFC reader, which is built into my tablet and trying to do it in Unity. The port of NFC in tablet is /dev/ttyS3. I can't use the using System.IO.Ports; library because Android doesn't support it.

Does anyone know a way to guide me toward a solution? Or has anyone dealt with this before?


Solution

  • So simply, I've given up on unity. You could make an aar library, import it into unity and reference it there.

    In the end, I stayed in android studio and focused on the port I needed and referenced and started listening.

    I found that the tablet uses a "GM 02 card reading module" which communicates via "ttyS3" and baud rate "115200".

    Maybe that will help someone.

    import android.os.Bundle
    import android.util.Log
    import android.widget.TextView
    import androidx.appcompat.app.AppCompatActivity
    import java.io.File
    import java.io.FileInputStream
    import java.io.IOException
    
    class MainActivity : AppCompatActivity() {
    
        private val serialPortPath = "/dev/ttyS3"
        private lateinit var inputStream: FileInputStream
        private lateinit var textViewData: TextView
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // Inicializace TextView
            textViewData = findViewById(R.id.textViewData)
            textViewData.text = "Waiting for data..."
    
            // Setting the serial port after initializing the UI components
            setupSerialPort()
        }
    
        private fun setupSerialPort() {
            val file = File(serialPortPath)
    
            if (!file.exists()) {
                updateTextView("Serial port $serialPortPath does not exist")
                return
            }
    
            if (!file.canRead() || !file.canWrite()) {
                updateTextView("No read/write access to $serialPortPath")
                return
            }
    
            try {
                inputStream = FileInputStream(file)
    
                Thread {
                    val buffer = ByteArray(64)
                    while (true) {
                        try {
                            val bytesRead = inputStream.read(buffer)
                            if (bytesRead > 0) {
                                // Přijatá data
                                val hexData = buffer.copyOf(bytesRead).joinToString(" ") {
                                    String.format("%02X", it)
                                }
                                Log.d("SerialPort", "Received raw data: $hexData")
    
                                // Verification of the beginning and end of the frame
                                if (buffer[0] == 0x02.toByte() && buffer[bytesRead - 1] == 0x03.toByte()) {
                                    val cardType = buffer[2]
                                    val cardData = buffer.copyOfRange(3, bytesRead - 2).joinToString("") {
                                        String.format("%02X", it)
                                    }
    
                                    updateTextView("Card Type: $cardType, Card Data: $cardData")
                                } else {
                                    // Neúplný rámec
                                    updateTextView("Incomplete or invalid frame: $hexData")
                                }
                            }
                        } catch (e: IOException) {
                            updateTextView("Error reading from serial port: ${e.message}")
                            break
                        }
                    }
                }.start()
    
            } catch (e: Exception) {
                updateTextView("Error initializing serial port: ${e.message}")
            }
        }
    
    
    
    
        private fun updateTextView(text: String) {
            if (::textViewData.isInitialized) {
                runOnUiThread {
                    textViewData.text = text
                }
            } else {
                Log.e("SerialPort", "TextView is not initialized yet!")
            }
        }
    
        override fun onDestroy() {
            super.onDestroy()
            try {
                inputStream.close()
            } catch (e: IOException) {
                Log.e("SerialPort", "Error closing serial port", e)
            }
        }
    }
    

    AndroidManifest permission

    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>