mortpiedra
mortpiedra

Reputation: 699

Have Bluetooth socket reconnect (in Python) after BT switched off and on again

I connect a bluetooth device in a python (3.10) program like this:

import socket
serverMACAddress = '00:07:80:e0:a4:fc'
port = 1
size = 1024
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.connect((serverMACAddress,port))

In the main loop I have this:

try:
    while 1: #main loop
        data = s.recv(size)
        if data:
            data_received( data )
        else:
            try:
                s.???? 
            except: 
                print("no data") 
except: 
    print("Closing socket")
    s.close()

Everything works fine unless the bluetooth device is switched off and then switched on again. I am trying to solve how to have the bluetooth device re-connect with the logic in the try-statement (s.????) within the loop, but I am unable to come up with a solution.

I am a beginner in BT and Python, but this should be pretty straightforward, right? I must be missing something very obvious. Any suggestions out there?

Modified version based on the suggestion by ukBaz:

try:
    while 1: #main loop
        try:
            data = s.recv(size)
        except socket.error():
            connected = False
            s = socket.socket
            while not connected:
                #attempt to re-connect
                try:
                    s.connect((serverMACAddress,port))
                    connected = True
                except:
                    time.sleep(5)
        if data:
            data_received( data )
except: 
    print("Closing socket")
    s.close()

After adding clientSocket.send:

while True: #main loop
    # attempt to reconnect, otherwise sleep for 2 seconds
    if not connected:
        try:
            # configure socket and connect to server
            clientSocket = socket.socket(
                socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM
            )

            clientSocket.connect((serverMACAddress, port))
            connected = True
            print("Connection successful")
        except socket.error:
            print("No connection, retrying")
#            time.sleep(2)
    # attempt to send and receive, otherwise reset connection status
    else:
        data = clientSocket.recv(size)
        if data:
            data_received( data )
        # Use send to check if scale is connected
        try:
            clientSocket.send(b"x")
        except socket.error:
            print("connection lost... reconnecting")
            # set connection status
            connected = False

Upvotes: 0

Views: 1265

Answers (1)

ukBaz
ukBaz

Reputation: 7994

I ran the following connecting to a remote HC-06 module on an Arduino. I tested the code below with Python 3.10 (Windows) and Python 3.8 (Linux) and it worked as expected on both.

It has a continuous while loop that if it is connected sends & receives data. If it is not connected, then it tries to connect. It uses except socket.error to detect there is an issue with the connection.

import socket
from time import sleep

host = "00:00:12:34:56:78"
port = 1
chunks = 1024

# keep track of connection status
connected = False

while True:
    # attempt to reconnect, otherwise sleep for 2 seconds
    if not connected:
        try:
            # configure socket and connect to server
            clientSocket = socket.socket(
                socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM
            )

            clientSocket.connect((host, port))
            connected = True
            print("Connection successful")
        except socket.error:
            print("No connection, retrying")
            sleep(2)
    # attempt to send and receive, otherwise reset connection status
    else:
        try:
            print("sending data...")
            clientSocket.send(b"Test")
            print("Reading data..")
            message = clientSocket.recv(chunks).decode("UTF-8")
            print("Recv'd", message)
        except socket.error:
            # set connection status
            connected = False
            print("connection lost... reconnecting")

If the socket is only doing read, then a timeout needs to be set so that it raises an exception. The value of the timeout might need to be tuned for your particular situation. As an example:

import socket
import time

import select

serverMACAddress = "00:00:12:34:56:78"
port = 1
size = 1024

# keep track of connection status
connected = False


def data_received(info):
    print(info)


while True: #main loop
    # attempt to reconnect, otherwise sleep for 2 seconds
    if not connected:
        try:
            # configure socket and connect to server
            clientSocket = socket.socket(
                socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM
            )

            clientSocket.connect((serverMACAddress, port))
            clientSocket.settimeout(5.5)
            connected = True
            print("Connection successful")
        except socket.error:
            print("No connection, retrying")
            time.sleep(2)
    # attempt to send and receive, otherwise reset connection status
    else:
        try:
            data = clientSocket.recv(size)
            print("Reading data..")
            if data:
                data_received(data)
        # Assume connection lost if read timeout raised
        except socket.timeout:
            # set connection status
            connected = False
            print("connection lost... reconnecting")

Upvotes: 1

Related Questions