首页 > 解决方案 > Android Kotlin 未从 USB FTDI 串行端口接收或读取数据

问题描述

我正在构建一个 Android 应用程序,它通过 USB 端口从另一个设备读取数据,正是这个 WaterRower 设备/机器,https: //www.waterrower.co.uk/waterrower-natural-rowing-machine ?gclid=Cj0KCQjw5auGBhDEARIsAFyNm9F2Q7Uq8tSHWTWgCelo4BgJUcK6c43_499CjVmOQSkgoI-E6zEjCU0aAiZSEAL.w_w

似乎它正在使用产品 id 10 和供应商 id 1240 的 FTDI 端口。我正在使用这个库进行串行端口通信,https://github.com/felHR85/UsbSerial。我可以打开端口。但是该应用程序没有从 WaterRower 机器接收或读取任何数据。

这是我的代码:

class NewDeviceListFragment: Fragment() {
    private lateinit var listView: RecyclerView
    private lateinit var listAdapter: DeviceListAdapter
    private lateinit var listItems: ArrayList<UsbDevice>
    private lateinit var emptyListMessage: TextView
    private lateinit var emptyListMessageWrapper: LinearLayout
    private lateinit var writeButton: AppCompatButton
    private lateinit var readButton: AppCompatButton
    private lateinit var showButton: AppCompatButton
    private lateinit var usbManager: UsbManager
    private lateinit var usbDevice: android.hardware.usb.UsbDevice
    private lateinit var tvReadDataText: TextView
    private lateinit var tvDriverDetails: TextView
    private val ACTION_USB_PERMISSION = "com.example.myapplication.USB_PERMISSION"
    private var readData: String = ""
    private var readCallback: UsbSerialInterface.UsbReadCallback = object: UsbSerialInterface.UsbReadCallback {
        override fun onReceivedData(arg0: ByteArray?) {
            try {
                var data: String? = null
                try {
                    data = String(arg0 as ByteArray, Charset.forName("UTF-8"))
                    "$data/n"
                    //tvReadDataText.setText(tvReadDataText.text.toString() + "\n" + data)
                    readData = readData + data
                } catch (e: UnsupportedEncodingException) {
                    e.printStackTrace()
                }
            } catch (e: Exception) {

                Bugsnag.notify(RuntimeException(e.message))
            }
        }
    }

    private val usbReceiver = object: BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == ACTION_USB_PERMISSION) {
                synchronized(this) {
                    val device: android.hardware.usb.UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)

                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        device?.apply {
                            //call method to set up device communication
                        }
                    } else {

                    }
                }
            }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_device_list, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        writeButton = view.findViewById(R.id.write_data_button)
        readButton = view.findViewById(R.id.read_data_button)
        showButton = view.findViewById(R.id.show_data_button)
        emptyListMessageWrapper = view.findViewById(R.id.device_list_empty_message_wrapper)
        emptyListMessage = view.findViewById(R.id.empty_list_message)
        listView = view.findViewById(R.id.list_view_device_list)
        tvReadDataText = view.findViewById(R.id.tv_read_data_text)
        tvDriverDetails = view.findViewById(R.id.tv_driver_details)
        listItems = ArrayList()
        setUpListView()

        readButton.setOnClickListener {
            readDataFromConnectedDevice()
        }

        showButton.setOnClickListener {
            tvReadDataText.setText(readData)
        }
    }

    private fun readDataFromConnectedDevice() {
        var usbConnection = usbManager.openDevice(usbDevice)
        var serial: UsbSerialDevice = UsbSerialDevice.createUsbSerialDevice(usbDevice, usbConnection)
        if (serial.open()) {
            readButton.setText("Port is now open")
            // 9600 is the Android default and 19200 for RowBots. max 115,200
            serial.setBaudRate(19200)
            serial.setDataBits(UsbSerialInterface.DATA_BITS_8)
            serial.setParity(UsbSerialInterface.PARITY_NONE)//FTPI change to parity odd
            serial.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF)
            serial.setDTR(true)
            serial.setRTS(true)
            serial.read(readCallback)
        } else {
            readButton.setText("Unable to open the port")
        }
    }

    private fun setUpListView() {
        listItems = getDeviceList()
        listView.layoutManager = LinearLayoutManager(activity as Activity)
        listAdapter = DeviceListAdapter(listItems)
        listView.adapter = listAdapter

        if (listItems.size < 1) {
            showEmptyListMessage("No device found")
        }
    }

    private fun getDeviceList(): ArrayList<UsbDevice> {
        var deviceList: ArrayList<UsbDevice> = ArrayList()

        // activity?.getSystemService(Context.USB_SERVICE) as UsbManager
        usbManager = activity?.getSystemService(Context.USB_SERVICE) as UsbManager
        for (device in usbManager.deviceList.values) {

            deviceList.add(
                UsbDevice(
                    id = device.deviceId.toString(),
                    name = device.deviceName + " : " + device.productName + " : " + device.manufacturerName,
                    model = "PID: ${device.productId} | VID: ${device.vendorId} | Interface: ${device.interfaceCount} (${device.getInterface(0).name})"
                )
            )

            //https://www.allaboutcircuits.com/projects/communicate-with-your-arduino-through-android/
            // here request the permission
            try {
                usbDevice = device
                var pi = PendingIntent.getBroadcast(activity, 0, Intent(ACTION_USB_PERMISSION), 0)
                val filter = IntentFilter(ACTION_USB_PERMISSION)
                activity?.registerReceiver(usbReceiver, filter)

                usbManager.requestPermission(usbDevice, pi)
            } catch (e: Exception) {

            }
        }

        if (usbManager.accessoryList != null) {
            for (accessory in usbManager.accessoryList) {
                deviceList.add(
                    UsbDevice(
                        id = accessory.serial.toString(),
                        name = accessory.description.toString(),
                        model = "accessory"
                    )
                )
            }
        }

        return deviceList
    }

    private fun showEmptyListMessage(message: String) {
        listView.visibility = View.GONE
        emptyListMessageWrapper.visibility = View.VISIBLE
        emptyListMessage.setText(message)
    }
}

它没有从 WaterRower 机器获取任何数据。

这是我的 device_filter.xml。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 0x0403 / 0x60??: FTDI -->
    <usb-device vendor-id="1027" product-id="24577" /> <!-- 0x6001: FT232R -->
    <usb-device vendor-id="1027" product-id="24592" /> <!-- 0x6010: FT2232H -->
    <usb-device vendor-id="1027" product-id="24593" /> <!-- 0x6011: FT4232H -->
    <usb-device vendor-id="1027" product-id="24596" /> <!-- 0x6014: FT232H -->
    <usb-device vendor-id="1027" product-id="24597" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->

    <!-- 0x10C4 / 0xEA??: Silabs CP210x -->
    <usb-device vendor-id="4292" product-id="60000" /> <!-- 0xea60: CP2102 and other CP210x single port devices -->
    <usb-device vendor-id="4292" product-id="60016" /> <!-- 0xea70: CP2105 -->
    <usb-device vendor-id="4292" product-id="60017" /> <!-- 0xea71: CP2108 -->

    <!-- 0x067B / 0x23?3: Prolific PL2303x -->
    <usb-device vendor-id="1659" product-id="8963" /> <!-- 0x2303: PL2303HX, HXD, TA, ... -->
    <usb-device vendor-id="1659" product-id="9123" /> <!-- 0x23a3: PL2303GC -->
    <usb-device vendor-id="1659" product-id="9139" /> <!-- 0x23b3: PL2303GB -->
    <usb-device vendor-id="1659" product-id="9155" /> <!-- 0x23c3: PL2303GT -->
    <usb-device vendor-id="1659" product-id="9171" /> <!-- 0x23d3: PL2303GL -->
    <usb-device vendor-id="1659" product-id="9187" /> <!-- 0x23e3: PL2303GE -->
    <usb-device vendor-id="1659" product-id="9203" /> <!-- 0x23f3: PL2303GS -->

    <!-- 0x1a86 / 0x?523: Qinheng CH34x -->
    <usb-device vendor-id="6790" product-id="21795" /> <!-- 0x5523: CH341A -->
    <usb-device vendor-id="6790" product-id="29987" /> <!-- 0x7523: CH340 -->

    <!-- CDC driver -->
    <usb-device vendor-id="9025" />                   <!-- 0x2341 / ......: Arduino (67 = 0x0043)-->
    <usb-device vendor-id="5824" product-id="1155" /> <!-- 0x16C0 / 0x0483: Teensyduino  -->
    <usb-device vendor-id="1003" product-id="8260" /> <!-- 0x03EB / 0x2044: Atmel Lufa -->
    <usb-device vendor-id="7855" product-id="4"    /> <!-- 0x1eaf / 0x0004: Leaflabs Maple -->
    <usb-device vendor-id="3368" product-id="516"  /> <!-- 0x0d28 / 0x0204: ARM mbed -->
    <usb-device vendor-id="1155" product-id="22336" /><!-- 0x0483 / 0x5740: ST CDC -->
    <usb-device vendor-id="1240" product-id="10" /><!-- 0x0d8 / 0x000a WaterRower -->
</resources>

我的代码有什么问题,我该如何解决?

标签: androidkotlinserial-portftdi

解决方案


推荐阅读