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

标签 java android python-3.x bluetooth pyjnius

我一直在摸索使用python for android jnius库从蓝牙RS232转换器获取数据。我原以为它会像 PySerial 库一样简单,但由于我还是 java 新手,所以实现是完全不同的。我很容易地创建了蓝牙连接,但是当我尝试读取或写入数据时,我得到一个 jnius.jnius.JavaExceptionNo methods matching your arguments,以及可用于 read 的方法是:'()I', '([B)I', '([BII)I'对于 write'(I)V', '([B)V', '([BII)V' .我尝试在开发人员 android 文档以及 DuckDuckGoing 中找到它,但不清楚。我也试过BufferedReader使用 readLine() 的示例 ( Here )方法,但我不断收到错误: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对象不返回任何数据?

我调用的 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 和上面的链接获得):
    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()

读写代码(来源:与上面的链接相同):
    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() 的输入。方法不返回错误并返回字符串。我清理了一下,但代码差别不大。主要的事情是我检查了 device != Noneif rfsocket.connected:在我的事件循环中创建 getInputStream 之前,以免重新创建套接字对象。必须进行更多测试才能看到主要问题在哪里。仍然不知道 read 的论点是什么和 write方法。 readLine()方法间歇地返回字符串或根本不返回字符串,我的事件循环似乎不适用于 readLine()方法。

更新更新:

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

终于破解了异常:

是的,这很令人兴奋!几个小时后,我注意到我无法再获得输入,只有异常(exception)。我试过 BufferedInputStream图书馆并得到相同的结果,没有更多的间歇性阅读。为什么?所以我重新 Apk 了 main昨晚的文件和繁荣间歇输入再次读取。
原因是如果我在 rfsocket 时创建了 java 对象。蓝牙对象未连接到指定端口,Null对象在另一个端口上初始化,由于某种原因,if 没有看到该端口。 block self.recv_stream is not Noneself.recv_stream != None .可能是因为他们不是Null对象,但 Null对于我指定的后续端口 1 套接字连接。readline()像我的例子一样工作,read()接受三个参数 bytes(), int offset, int len(bytes()这在 jnius.jnius.exception 中并不清楚象形文字的消息。还在摸索write方法。您可以在 BufferedReader 中指定的一件事方法是您要读取的 block 大小的第二个参数,或者在 java 中使用 defaultCharBufferSize .

最佳答案

所以我发布了我的答案,因为我已经解决了所有问题。
要连接到我在 GitHub example 上构建的蓝牙按照 android developers site 上的建议进行操作.在创建 getOutputStream 之前,我必须明确设置自己的套接字。和 getInputStream 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()

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

关于java - 如何使用蓝牙 getInputStream 和 getOutputStream 的 pyjnius 读写参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58477961/

相关文章:

java - 使用 activemq 添加 camunda-bpm-wildfly 并在同一个 docker 容器中运行

java - 创建方法并更新字符串

python - 删除 NaN 单元格并根据日期时间索引移动非空值

java - SWING 的轮类日历

java - 如果实例没有分配泛型类型,则每个循环问题中的泛型

android - 如何摆脱 CardView 中 ImageView 周围的空白

android - 如何触发 ActivityAware 覆盖方法 onAttachedToActivity()?

xml - python etree.ElementTree 解析困难的命名空间

python - 计算单词中的音节数

java - 在正文中使用 application/x-www-form-urlencoded 的 400 错误白色 Java Post