如何使用 pyjnius 读取和写入蓝牙 getInputStream 和 getOutputStream 的参数?

How to use the pyjnius read and write arguments for Bluetooth getInputStream and getOutputStream?

我一直在摸索如何使用 python for android jnius 库从蓝牙 RS232 转换器获取数据。我原以为它会像 PySerial 库一样简单,但由于我对 java 还是个新手,所以实现方式大不相同。
我很容易地创建了蓝牙连接,但是当我尝试读取或写入数据时,我得到一个 jnius.jnius.JavaException No methods matching your arguments, 并且 read 可用的方法是: '()I', '([B)I', '([BII)I'write'(I)V', '([B)V', '([BII)V'。我尝试在开发人员 android 文档以及 DuckDuckGoing 中找到它,但不清楚。
我还使用 readLine() 方法尝试了 BufferedReader 示例 (),但我不断收到错误消息:JavaException: JVM exception occurred: Attempt to invoke virtual method 'int java.io.InputStream.read(byte[], int, int)' on a null object reference.

有人可以指点我的文档来理解上面的读写参数吗?
另外,请帮助我理解为什么 read, readLine() and write 对象没有 return 任何数据?

Java 我调用的库:

BluetoothAdapter = autoclass('android.bluetooth.BluetoothAdapter')
BluetoothDevice = autoclass('android.bluetooth.BluetoothDevice')
BluetoothSocket = autoclass('android.bluetooth.BluetoothSocket')
InputStreamReader = autoclass('java.io.InputStreamReader')
BufferedReader = autoclass('java.io.BufferedReader')
UUID = autoclass('java.util.UUID')
System = autoclass('java.lang.System')

连接代码(从Github及以上link获得):

    def get_socket_stream(self, name):
        paired_devices = BluetoothAdapter.getDefaultAdapter().getBondedDevices().toArray()
        self.rfsocket == None
        for device in paired_devices:
            if device.getName() == name:
                if device.bluetoothEnabled:
                    if not device.connected:
                        self.rfsocket = device.createInsecureRfcommSocketToServiceRecord(
                            UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"))
                        self.reader = InputStreamReader(self.rfsocket.getInputStream(), 'LATIN-1')
                        recv_stream = BufferedReader(self.reader)
                        send_stream = self.rfsocket.getOutputStream()
                        break
        print(self.rfsocket.getRemoteDevice().getName())
        if self.rfsocket.port <= 0:
            self.rfsocket = device.createRfcommSocket(1)
            if not self.rfsocket.connected:
                print('port two: ',self.rfsocket.port)
                self.rfsocket.connect()

读写代码(来源:同上link):

    def GetBSerial(self):
        self.messager('Trying Serial')
        self.recv_stream, self.send_stream = self.get_socket_stream(devicename)
        if  not self.rfsocket.connected and self.recv_stream == None:
            print("Get paired device failed")
        else:
            print('Initiating trigger')
            self.weight_ticker()
    def GetInput(self):
        self.send_stream.write("Hallo\r\n")
        self.send_stream.flush
        if self.rfsocket.connected and self.recv_stream != None:
            if self.weigh_tme > 0:
                while self.recv_stream.ready != None:
                    try:
                        self.scale_output = self.recv_stream.readLine()
                    except jnius.jnius.JavaException as e:
                        print("JavaException: ", e, self.rfsocket.connected)
                    except ValueError as e:
                        print("Misc error: ", e)

                    try:
                        self.show_input(self.scale_output)
                    except ValueError:
                        pass

更新:

所以我终于使用 readLine() 方法得到了输入,而不是 return 错误和 return 字符串。我稍微清理了一下,但代码差别不大。不过最主要的是我在事件循环中创建 getInputStream 之前检查了 device != Noneif rfsocket.connected: 是否,以免重新创建套接字对象。必须进行更多测试以查看主要问题出在哪里。仍然不知道 readwrite 方法的参数是什么。 readLine() 方法 return 间歇地或根本不发送字符串,我的事件循环似乎不适用于 readLine() 方法。

更新更新:

事件循环再次运行。我的错,我没有正确调用触发器对象。 readLine() 方法有一个奇怪的模式,在第一次读取时它给我 JavaException: JVM exception occurred: Attempt to invoke virtual method 'int java.io.InputStream.available()' on a null object reference,随后的读取给我一些预期的字符串或一个空字符串。当我使用 PySerial 通过硬线接收数据时,我有类似的字符串片段 returned。解决方案是重置输入缓冲区。上述 java 库中是否有类似的东西?

终于破解异常:

是的,这很令人兴奋!几个小时后,我注意到我无法再获得输入,只有例外。我尝试了 BufferedInputStream 库,得到了相同的结果,不再有断断续续的阅读。为什么?所以我重新 Apk 了昨晚的 main 文件,并再次读取了 boom 间歇性输入。
原因是如果我在 rfsocket 蓝牙对象未连接到指定端口时创建 java 对象,Null 对象是在不同的端口上初始化的,由于某种原因未被看到ifself.recv_stream is not Noneself.recv_stream != None。可能是因为它们不是 Null 对象,而是我指定的后续端口 1 套接字连接的 Null
readline() 和我的示例一样工作,read() 采用三个参数 bytes(), int offset, int len(bytes(),这在 jnius.jnius.exception 象形文字的消息中并不清楚。仍在研究 write 方法。您可以在 BufferedReader 方法中指定的一件事是您要读取的块大小的第二个参数,或者在 java 中说 defaultCharBufferSize.

所以我发布我的答案,因为我已经解决了所有问题。
为了连接到蓝牙,我建立在 GitHub example by following the suggestions on the android developers site 上。在创建 getOutputStreamgetInputStream java 对象之前,我必须明确设置自己的套接字,否则连接端口和对象将不相同。你只需要调用GetBSerial()连接

    def get_socket_stream(self, name):
        defaultCharBufferSize = 8192
        try:
            blueAdapt = BluetoothAdapter.getDefaultAdapter()
            if self.rfsocket is not None:
                if self.rfsocket.connected:
                    reader = InputStreamReader(self.rfsocket.getInputStream(), getEncode)
                    recv_stream = BufferedReader(reader)
                    send_stream = self.rfsocket.getOutputStream()
                else:
                    self.rfsocket = self.device.createRfcommSocketToServiceRecord(UUID.fromString(getUuid))
                    if self.get_port_connect():
                        reader = InputStreamReader(self.rfsocket.getInputStream(), getEncode)
                        recv_stream = BufferedReader(reader, defaultCharBufferSize)
                        send_stream = self.rfsocket.getOutputStream()
            else:
                if blueAdapt is not None:
                    if blueAdapt.isEnabled():
                        paired_devices = blueAdapt.getBondedDevices().toArray()
                        self.rfsocket = None
                        for self.device in paired_devices:
                            if self.device.getName() == name:
                                if self.device.bluetoothEnabled:
                                    self.rfsocket = self.device.createRfcommSocketToServiceRecord(
                                        UUID.fromString(getUuid))
                                    if self.rfsocket is not None:
                                        if self.get_port_connect(): #connect and set the port before creating java objects
                                            reader = InputStreamReader(self.rfsocket.getInputStream(), getEncode)
                                            recv_stream = BufferedReader(reader, defaultCharBufferSize)
                                            send_stream = self.rfsocket.getOutputStream()
                                            break
                    else:
                        self.ids.bluet_info.text = '[b]Bluetooth not enabled[/b]'
            if recv_stream is not None and send_stream is not None:
                return recv_stream, send_stream
            else:
                return False, False
        except UnboundLocalError as e:
            return False, False
        except TypeError as e:
            return False, False
    def get_port_connect(self):
        try:
            if self.rfsocket.port <= 0:
                self.rfsocket = self.device.createRfcommSocket(1) #set the port explicitly
                if not self.rfsocket.connected:
                    self.rfsocket.connect()
            else:
                if not self.rfsocket.connected:
                    self.rfsocket.connect()
            if self.rfsocket.connected:
                self.ids.bluet_info.text = '[b]Connected[/b]'
            return True
        except jnius.jnius.JavaException as e:
            self.ids.bluet_info.text = '[b]Cannot connect to socket[/b]'
    def GetBSerial(self):
        try:
            getDevname = self.the.config.get('bluetoothsettings', 'stringbluetdevname')
            self.recv_stream, self.send_stream = self.get_socket_stream(getDevname)
        except jnius.jnius.JavaException as e:
            self.ids.bluet_info.text = '[b]Not Connected[/b]'

我用的是readLine()的方法,但是要用read()的方法,有两种建字符串的方法。在外部(我只试过这个)或在数组中。
进口:

CharBuilder = autoclass('java.lang.Character')

外部:

if self.recv_stream.ready() != None:
    r = self.recv_stream.read()
    theChar = CharBuilder.toChars(r) #gives a tuple of which the first element is a character
    self.read += theChar[0]

您必须尝试构建字符串才能知道字符串必须从哪里开始。

write() 方法的第一件事是它需要一个字节对象。因此,您构建了一个 bytearray() 并将其用作参数。使用 ESC/POS 打印机初始化命令和字符串的示例:

i = [27,64] #ASCII escape integer and at sign integer
pre = bytearray(i)
cmd = 'Hello You\n'.encode('UTF-8')
#extend bytearray
pre.extend(cmd)
self.send_stream.write(pre)
self.send_stream.flush()

还不知道如何一次性创建字节数组整数和字符串。