Good day!


I concretize and repeat for a better understanding:

  1. I work in the Spyder 3.0.2 (Python 3.5), ОС Windows 10 Pro environment Spyder 3.0.2 (Python 3.5), ОС Windows 10 Pro
  2. I use a regular Bluetooth laptop module for communication via RFCOMM protocol with a Bluetooth module HC-06
  3. I use the PyBluez module

Simplified script code (the search and connection process is omitted by the specified name):

 import bluetooth bluetooth_addr = '20:16:01:11:67:40' socket_port = 1 socket = bluetooth.BluetoothSocket( bluetooth.RFCOMM ) socket.connect( (bluetooth_addr, socket_port) ) 

The code is working, the connection is happening, data is being transferred.

However, there is a problem with the socket.recv (buffsize) function. It hangs tightly in case the number of bytes available in the socket buffer is less than the function argument — buffsize ... Which means you need to know the number of bytes in the socket buffer to avoid malfunctions.

I see two ways to solve the problem - somehow find out the number of bytes in the socket buffer, or use timeouts.

Described and working solution using timeout:

 In [1]: import bluetooth In [2]: bluetooth_addr = '20:16:01:11:67:40' In [3]: socket_port = 1 In [4]: socket = bluetooth.BluetoothSocket( bluetooth.RFCOMM ) In [5]: socket.settimeout (1) In [6]: socket.connect( (bluetooth_addr, socket_port) ) In [7]: socket.recv (1) Traceback (most recent call last): File "<ipython-input-7-30e8d180471b>", line 1, in <module> socket.recv (1) File "C:\Users\123\Anaconda3\lib\site-packages\pybluez-0.22-py3.5-win- amd64.egg\bluetooth\msbt.py", line 84, in recv return bt.recv (self._sockfd, numbytes) OSError 

however, for several reasons, it is unacceptable.


In the discussion, it was suggested to use the variable socket.MSG_DONTWAIT , but there is no such variable in the BluetoothSocket class.

Also clarification was given:

| >>> import socket >>> socket.MSG_DONTWAIT 64 socket is not your object, but an eri module

The meaning of which has not reached me yet. To check in the console, IPython executed the following code:


 In [1]: import bluetooth In [2]: In [3]: import socket In [4]: socket = bluetooth.BluetoothSocket( bluetooth.RFCOMM ) In [5]: bluetooth_devices = bluetooth.discover_devices() In [6]: bluetooth_devices Out[6]: ['20:12:11:22:87:98', '20:16:01:11:67:40', 'E4:E0:C5:C2:34:26'] In [7]: socket.connect( ('20:16:01:11:67:40', 1) ) In [8]: socket.MSG_DONTWAIT Traceback (most recent call last): File "<ipython-input-8-1b2974ae0a63>", line 1, in <module> socket.MSG_DONTWAIT AttributeError: 'BluetoothSocket' object has no attribute 'MSG_DONTWAIT' 

And so - what am I doing wrong? And yet, is it possible through the BluetoothSocket class to find out the number of bytes in its buffer for implementing a non-hanging script?

  • can be read with flags=socket.MSG_DONTWAIT and in this case it will return what is in the buffer. Analyze the data and if you do not have enough - read more. - KoVadim Nov.
  • Unfortunately, normally insert the code did not work. The point is that pybluez does not have such an attribute as MSG_DONTWAIT - Alexey Simakov
  • Normally socket.recv (bufsize) can return less than bufsize bytes. If you put a timeout and recv (101) throws an exception instead of returning the already available 100 bytes, the implementation is broken. - jfs
  • Yeah, on Linux OS it worked - if the data buffer was less than requested, it returned everything in the buffer. However, under Windows, it works as described above ... And cross-platform is needed - Alexey Simakov
  • one
    >>> import socket >>> socket.MSG_DONTWAIT 64 socket is not your object, but a module - eri

1 answer 1

And why not use the socket.setblocking(False) method and read bytes in an infinite loop while they are there or before a certain character.

Like this:

 msg = "" socket.setblocking(False) while True: try: b = socket.recv(1) msg += b.decode() if "/r/n" in msg: break except BluetoothError: pass 

In the third block of code, you have an extra import import socket , since you do not use it and replace it with BluetoothSocket .

  • > In the third block of code, you have an extra import import socket, since you do not use it and replace it with BluetoothSocket. - This was on the advice of comments trying to refer to variables of the class socket - Alexey Simakov
  • Do I understand correctly that unlocking a socket with the socket.setblocking(False) function provides an instant socket.recv(buffsize) ? - Alexey Simakov
  • Yes exactly. If the call to socket.recv no data, a BluetoothError exception is thrown. And the execution of the program goes further. - Avernial
  • There is a problem - the PyBluez module refuses to work with its own exceptions. Only OSError . But this is a topic for a separate issue. - Alexey Simakov