From 82469dc1aa6320ef9d00616593789ae4991dd472 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 09:44:50 +0200 Subject: [PATCH 01/13] 'black' --- bleClient.py | 117 ++++++++++++++++++++++++++++++++----------------- bleServer.py | 121 +++++++++++++++++++++++++++++---------------------- 2 files changed, 148 insertions(+), 90 deletions(-) diff --git a/bleClient.py b/bleClient.py index 7271494..f632b95 100755 --- a/bleClient.py +++ b/bleClient.py @@ -9,29 +9,29 @@ import time import logging import logging.config -import json #Uses JSON package -import cPickle as pickle #Serializing and de-serializing a Python object structure -from bluetooth import * #Python Bluetooth library +import json # Uses JSON package +import cPickle as pickle # Serializing and de-serializing a Python object structure +from bluetooth import * # Python Bluetooth library + +logger = logging.getLogger("bleClientLogger") -logger = logging.getLogger('bleClientLogger') def startLogging( - default_path='configLogger.json', - default_level=logging.INFO, - env_key='LOG_CFG' + default_path="configLogger.json", default_level=logging.INFO, env_key="LOG_CFG" ): - #Setup logging configuration + # Setup logging configuration path = default_path value = os.getenv(env_key, None) if value: path = value if os.path.exists(path): - with open(path, 'rt') as f: + with open(path, "rt") as f: config = json.load(f) logging.config.dictConfig(config) else: logging.basicConfig(level=default_level) + class bleClient: def __init__(self, clientSocket=None): if clientSocket is None: @@ -39,7 +39,7 @@ def __init__(self, clientSocket=None): self.bleService = None self.addr = None self.uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" - self.jsonFile ="text.json" + self.jsonFile = "text.json" self.jsonObj = None else: self.clientSocket = clientSocket @@ -48,52 +48,82 @@ def getBluetoothServices(self): try: logger.info("Searching for Bluetooth services ...") for reConnect in range(2, 4): - bleService = find_service( uuid = self.uuid, address = self.addr ) + bleService = find_service(uuid=self.uuid, address=self.addr) if len(bleService) == 0: - logger.info("Re-connecting Bluetooth services : %d attempt", reConnect) + logger.info( + "Re-connecting Bluetooth services : %d attempt", reConnect + ) else: break - if not bleService: raise SystemExit(), KeyboardInterrupt() + if not bleService: + raise Exception([SystemExit(), KeyboardInterrupt()]) else: logger.info("Found Bluetooth services ..") - logger.info("Protocol\t: %s", bleService[0]['protocol']) - logger.info("Name\t\t: %s", bleService[0]['name']) - logger.info("Service-id\t: %s", bleService[0]['service-id']) - logger.info("Profiles\t: %s", bleService[0]['profiles']) - logger.info("Service-class\t: %s", bleService[0]['service-classes']) - logger.info("Host\t\t: %s", bleService[0]['host']) - logger.info("Provider\t: %s", bleService[0]['provider']) - logger.info("Port\t\t: %s", bleService[0]['port']) - logger.info("Description\t: %s", bleService[0]['description']) + logger.info("Protocol\t: %s", bleService[0]["protocol"]) + logger.info("Name\t\t: %s", bleService[0]["name"]) + logger.info("Service-id\t: %s", bleService[0]["service-id"]) + logger.info("Profiles\t: %s", bleService[0]["profiles"]) + logger.info("Service-class\t: %s", bleService[0]["service-classes"]) + logger.info("Host\t\t: %s", bleService[0]["host"]) + logger.info("Provider\t: %s", bleService[0]["provider"]) + logger.info("Port\t\t: %s", bleService[0]["port"]) + logger.info("Description\t: %s", bleService[0]["description"]) self.bleService = bleService except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: - logger.error("Couldn't find the RaspberryPi Bluetooth service : Invalid uuid", exc_info=True) + logger.error( + "Couldn't find the RaspberryPi Bluetooth service : Invalid uuid", + exc_info=True, + ) def getBluetoothSocket(self): try: - self.clientSocket=BluetoothSocket( RFCOMM ) - logger.info("Bluetooth client socket successfully created for RFCOMM service ...") + self.clientSocket = BluetoothSocket(RFCOMM) + logger.info( + "Bluetooth client socket successfully created for RFCOMM service ..." + ) except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: - logger.error("Failed to create the bluetooth client socket for RFCOMM service ... ", exc_info=True) + logger.error( + "Failed to create the bluetooth client socket for RFCOMM service ... ", + exc_info=True, + ) def getBluetoothConnection(self): try: bleServiceInfo = self.bleService[0] - logger.info("Connecting to \"%s\" on %s with port %s" % (bleServiceInfo['name'], bleServiceInfo['host'], bleServiceInfo['port'])) - self.clientSocket.connect((bleServiceInfo['host'], bleServiceInfo['port'])) - logger.info("Connected successfully to %s "% (bleServiceInfo['name'])) + logger.info( + 'Connecting to "%s" on %s with port %s' + % ( + bleServiceInfo["name"], + bleServiceInfo["host"], + bleServiceInfo["port"], + ) + ) + self.clientSocket.connect((bleServiceInfo["host"], bleServiceInfo["port"])) + logger.info("Connected successfully to %s " % (bleServiceInfo["name"])) except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: - logger.error("Failed to connect to \"%s\" on address %s with port %s" % (bleServiceInfo['name'], bleServiceInfo['host'], bleServiceInfo['port']), exc_info=True) + logger.error( + 'Failed to connect to "%s" on address %s with port %s' + % ( + bleServiceInfo["name"], + bleServiceInfo["host"], + bleServiceInfo["port"], + ), + exc_info=True, + ) def readJsonFile(self): try: - jsonFileObj = open(self.lsonFile,"r") + jsonFileObj = open(self.lsonFile, "r") logger.info("File successfully uploaded to %s" % (jsonFileObj)) self.jsonObj = json.load(jsonFileObj) - logger.info("Content loaded successfully from the %s file" %(self.jsonFile)) + logger.info( + "Content loaded successfully from the %s file" % (self.jsonFile) + ) jsonFileObj.close() except (Exception, IOError) as e: - logger.error("Failed to load content from the %s" % (self.jsonFile), exc_info=True) + logger.error( + "Failed to load content from the %s" % (self.jsonFile), exc_info=True + ) def serializeData(self): try: @@ -101,20 +131,28 @@ def serializeData(self): logger.info("Object successfully converted to a serialized string") return serializedData except (Exception, pickle.PicklingError) as e: - logger.error("Failed to convert json object to serialized string", exc_info=True) + logger.error( + "Failed to convert json object to serialized string", exc_info=True + ) def sendData(self, _serializedData): try: logger.info("Sending data over bluetooth connection") - _serializedData =str(len(_serializedData))+ ":"+_serializedData + _serializedData = str(len(_serializedData)) + ":" + _serializedData self.clientSocket.send(_serializedData) time.sleep(0.5) while True: - dataRecv= self.clientSocket.recv(1024) - if dataRecv in ['EmptyBufferResend', 'CorruptedBufferResend', 'DelimiterMissingBufferResend']: + dataRecv = self.clientSocket.recv(1024) + if dataRecv in [ + "EmptyBufferResend", + "CorruptedBufferResend", + "DelimiterMissingBufferResend", + ]: self.clientSocket.send(_serializedData) time.sleep(0.5) - logger.info("%s : Re-sending data over bluetooth connection" %(dataRecv)) + logger.info( + "%s : Re-sending data over bluetooth connection" % (dataRecv) + ) else: break logger.info("Data sent successfully over bluetooth connection") @@ -148,7 +186,8 @@ def stop(self): # Disconnecting bluetooth service self.closeBluetoothSocket() -if __name__ == '__main__': + +if __name__ == "__main__": startLogging() logger.info("Setup logging configuration") bleClnt = bleClient() diff --git a/bleServer.py b/bleServer.py index 04ae77b..f8e4a90 100755 --- a/bleServer.py +++ b/bleServer.py @@ -9,16 +9,15 @@ import time import logging import logging.config -import json # Uses JSON package -import cPickle as pickle # Serializing and de-serializing a Python object structure -from bluetooth import * # Python Bluetooth library +import json # Uses JSON package +import cPickle as pickle # Serializing and de-serializing a Python object structure +from bluetooth import * # Python Bluetooth library + +logger = logging.getLogger("bleServerLogger") -logger = logging.getLogger('bleServerLogger') def startLogging( - default_path='configLogger.json', - default_level=logging.INFO, - env_key='LOG_CFG' + default_path="configLogger.json", default_level=logging.INFO, env_key="LOG_CFG" ): # Setup logging configuration path = default_path @@ -26,20 +25,21 @@ def startLogging( if value: path = value if os.path.exists(path): - with open(path, 'rt') as f: + with open(path, "rt") as f: config = json.load(f) logging.config.dictConfig(config) else: logging.basicConfig(level=default_level) + class bleServer: def __init__(self, serverSocket=None, clientSocket=None): if serverSocket is None: self.dataObj = None self.serverSocket = serverSocket self.clientSocket = clientSocket - self.serviceName="BluetoothServices" - self.jsonFile ="text.json" + self.serviceName = "BluetoothServices" + self.jsonFile = "text.json" self.uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" else: self.serverSocket = serverSocket @@ -47,36 +47,50 @@ def __init__(self, serverSocket=None, clientSocket=None): def getBluetoothSocket(self): try: - self.serverSocket=BluetoothSocket( RFCOMM ) - logger.info("Bluetooth server socket successfully created for RFCOMM service...") + self.serverSocket = BluetoothSocket(RFCOMM) + logger.info( + "Bluetooth server socket successfully created for RFCOMM service..." + ) except (BluetoothError, SystemExit, KeyboardInterrupt) as e: logger.error("Failed to create the bluetooth server socket ", exc_info=True) def getBluetoothConnection(self): try: - self.serverSocket.bind(("",PORT_ANY)) - logger.info("Bluetooth server socket bind successfully on host "" to PORT_ANY...") + self.serverSocket.bind(("", PORT_ANY)) + logger.info( + "Bluetooth server socket bind successfully on host " " to PORT_ANY..." + ) except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: - logger.error("Failed to bind server socket on host to PORT_ANY ... ", exc_info=True) + logger.error( + "Failed to bind server socket on host to PORT_ANY ... ", exc_info=True + ) try: self.serverSocket.listen(1) - logger.info("Bluetooth server socket put to listening mode successfully ...") + logger.info( + "Bluetooth server socket put to listening mode successfully ..." + ) except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: - logger.error("Failed to put server socket to listening mode ... ", exc_info=True) + logger.error( + "Failed to put server socket to listening mode ... ", exc_info=True + ) try: - port=self.serverSocket.getsockname()[1] + port = self.serverSocket.getsockname()[1] logger.info("Waiting for connection on RFCOMM channel %d" % (port)) except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: - logger.error("Failed to get connection on RFCOMM channel ... ", exc_info=True) + logger.error( + "Failed to get connection on RFCOMM channel ... ", exc_info=True + ) def advertiseBluetoothService(self): try: - advertise_service( self.serverSocket, self.serviceName, - service_id = self.uuid, - service_classes = [ self.uuid, SERIAL_PORT_CLASS ], - profiles = [ SERIAL_PORT_PROFILE ], - # protocols = [ OBEX_UUID ] - ) + advertise_service( + self.serverSocket, + self.serviceName, + service_id=self.uuid, + service_classes=[self.uuid, SERIAL_PORT_CLASS], + profiles=[SERIAL_PORT_PROFILE], + # protocols = [ OBEX_UUID ] + ) logger.info("%s advertised successfully ..." % (self.serviceName)) except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: logger.error("Failed to advertise bluetooth services ... ", exc_info=True) @@ -91,12 +105,12 @@ def acceptBluetoothConnection(self): def recvData(self): try: while True: - data= self.clientSocket.recv(1024) + data = self.clientSocket.recv(1024) if not data: self.clientSocket.send("EmptyBufferResend") # remove the length bytes from the front of buffer # leave any remaining bytes in the buffer! - dataSizeStr, ignored, data = data.partition(':') + dataSizeStr, ignored, data = data.partition(":") dataSize = int(dataSizeStr) if len(data) < dataSize: self.clientSocket.send("CorruptedBufferResend") @@ -110,7 +124,7 @@ def recvData(self): def deserializedData(self, _dataRecv): try: - self.dataObj=pickle.loads(_dataRecv) + self.dataObj = pickle.loads(_dataRecv) logger.info("Serialized string converted successfully to object") except (Exception, pickle.UnpicklingError) as e: logger.error("Failed to de-serialized string ... ", exc_info=True) @@ -118,17 +132,21 @@ def deserializedData(self, _dataRecv): def writeJsonFile(self): try: # Open a file for writing - jsonFileObj = open(self.jsonFile,"w") - logger.info("%s file successfully opened to %s" % (self.jsonFile, jsonFileObj)) + jsonFileObj = open(self.jsonFile, "w") + logger.info( + "%s file successfully opened to %s" % (self.jsonFile, jsonFileObj) + ) # Save the dictionary into this file # (the 'indent=4' is optional, but makes it more readable) - json.dump(self.dataObj,jsonFileObj, indent=4) - logger.info("Content dumped successfully to the %s file" %(self.jsonFile)) + json.dump(self.dataObj, jsonFileObj, indent=4) + logger.info("Content dumped successfully to the %s file" % (self.jsonFile)) # Close the file jsonFileObj.close() - logger.info("%s file successfully closed" %(self.jsonFile)) + logger.info("%s file successfully closed" % (self.jsonFile)) except (Exception, IOError) as e: - logger.error("Failed to write json contents to the file ... ", exc_info=True) + logger.error( + "Failed to write json contents to the file ... ", exc_info=True + ) def closeBluetoothSocket(self): try: @@ -139,28 +157,29 @@ def closeBluetoothSocket(self): logger.error("Failed to close the bluetooth sockets ", exc_info=True) def start(self): - # Create the server socket - self.getBluetoothSocket() - # get bluetooth connection to port # of the first available - self.getBluetoothConnection() - # advertising bluetooth services - self.advertiseBluetoothService() - # Accepting bluetooth connection - self.acceptBluetoothConnection() + # Create the server socket + self.getBluetoothSocket() + # get bluetooth connection to port # of the first available + self.getBluetoothConnection() + # advertising bluetooth services + self.advertiseBluetoothService() + # Accepting bluetooth connection + self.acceptBluetoothConnection() def receive(self): - # receive data - dataRecv=self.recvData() - # de-serializing data - self.deserializedData(dataRecv) - # Writing json object to the file - self.writeJsonFile() + # receive data + dataRecv = self.recvData() + # de-serializing data + self.deserializedData(dataRecv) + # Writing json object to the file + self.writeJsonFile() def stop(self): - # Disconnecting bluetooth sockets - self.closeBluetoothSocket() + # Disconnecting bluetooth sockets + self.closeBluetoothSocket() + -if __name__ == '__main__': +if __name__ == "__main__": startLogging() bleSvr = bleServer() bleSvr.start() From 07925929e81c2ae26ac333e520a94c8bd6adf249 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 09:44:56 +0200 Subject: [PATCH 02/13] ignore venv --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f7275bb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv/ From 65296c4b491c1287458a812f0a0c63d88a7a1582 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 09:53:13 +0200 Subject: [PATCH 03/13] Move from cPickle to pickle, document code, make it Python3 compliant --- bleClient.py | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/bleClient.py b/bleClient.py index f632b95..b879be0 100755 --- a/bleClient.py +++ b/bleClient.py @@ -5,12 +5,14 @@ # Desc: Bluetooth client application that uses RFCOMM sockets # intended for use with rfcomm-server import os -import sys import time import logging import logging.config import json # Uses JSON package -import cPickle as pickle # Serializing and de-serializing a Python object structure + +# import cPickle as pickle # Serializing and de-serializing a Python object structure +import pickle + from bluetooth import * # Python Bluetooth library logger = logging.getLogger("bleClientLogger") @@ -19,20 +21,23 @@ def startLogging( default_path="configLogger.json", default_level=logging.INFO, env_key="LOG_CFG" ): + """Init the logging subsystem""" # Setup logging configuration path = default_path value = os.getenv(env_key, None) if value: path = value if os.path.exists(path): - with open(path, "rt") as f: - config = json.load(f) + with open(path, "rt", encoding="utf-8") as file_handle: + config = json.load(file_handle) logging.config.dictConfig(config) else: logging.basicConfig(level=default_level) class bleClient: + """Provide Bluetooth Client interface""" + def __init__(self, clientSocket=None): if clientSocket is None: self.clientSocket = clientSocket @@ -45,6 +50,7 @@ def __init__(self, clientSocket=None): self.clientSocket = clientSocket def getBluetoothServices(self): + """Get BT service""" try: logger.info("Searching for Bluetooth services ...") for reConnect in range(2, 4): @@ -69,25 +75,27 @@ def getBluetoothServices(self): logger.info("Port\t\t: %s", bleService[0]["port"]) logger.info("Description\t: %s", bleService[0]["description"]) self.bleService = bleService - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error( "Couldn't find the RaspberryPi Bluetooth service : Invalid uuid", exc_info=True, ) def getBluetoothSocket(self): + """Get the BT socket""" try: self.clientSocket = BluetoothSocket(RFCOMM) logger.info( "Bluetooth client socket successfully created for RFCOMM service ..." ) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error( "Failed to create the bluetooth client socket for RFCOMM service ... ", exc_info=True, ) def getBluetoothConnection(self): + """Get the BT connection""" try: bleServiceInfo = self.bleService[0] logger.info( @@ -100,7 +108,7 @@ def getBluetoothConnection(self): ) self.clientSocket.connect((bleServiceInfo["host"], bleServiceInfo["port"])) logger.info("Connected successfully to %s " % (bleServiceInfo["name"])) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error( 'Failed to connect to "%s" on address %s with port %s' % ( @@ -112,30 +120,33 @@ def getBluetoothConnection(self): ) def readJsonFile(self): + """Read JSON file""" try: - jsonFileObj = open(self.lsonFile, "r") + jsonFileObj = open(self.jsonFile, "r", encoding="utf-8") logger.info("File successfully uploaded to %s" % (jsonFileObj)) self.jsonObj = json.load(jsonFileObj) logger.info( "Content loaded successfully from the %s file" % (self.jsonFile) ) jsonFileObj.close() - except (Exception, IOError) as e: + except (Exception, IOError) as _: logger.error( "Failed to load content from the %s" % (self.jsonFile), exc_info=True ) def serializeData(self): + """Serialize the data""" try: serializedData = pickle.dumps(self.jsonObj) logger.info("Object successfully converted to a serialized string") return serializedData - except (Exception, pickle.PicklingError) as e: + except (Exception, pickle.PicklingError) as _: logger.error( "Failed to convert json object to serialized string", exc_info=True ) def sendData(self, _serializedData): + """Send data via BT""" try: logger.info("Sending data over bluetooth connection") _serializedData = str(len(_serializedData)) + ":" + _serializedData @@ -156,17 +167,19 @@ def sendData(self, _serializedData): else: break logger.info("Data sent successfully over bluetooth connection") - except (Exception, IOError) as e: + except (Exception, IOError) as _: logger.error("Failed to send data over bluetooth connection", exc_info=True) def closeBluetoothSocket(self): + """Close BT socket""" try: self.clientSocket.close() logger.info("Bluetooth client socket successfully closed ...") - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error("Failed to close the bluetooth client socket ", exc_info=True) def start(self): + """Start the BT interface""" # Search for the RaspberryPi Bluetooth service self.getBluetoothServices() # Create the client socket @@ -175,6 +188,8 @@ def start(self): self.getBluetoothConnection() def send(self): + """Send content""" + # Load the contents from the file, which creates a new json object self.readJsonFile() # Convert the json object to a serialized string @@ -183,6 +198,8 @@ def send(self): self.sendData(serializedData) def stop(self): + """Stop the BT interface""" + # Disconnecting bluetooth service self.closeBluetoothSocket() From b74272cc4d07d272f8768db43bfc18586e3078c5 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 09:55:13 +0200 Subject: [PATCH 04/13] pip3 pybluez doesn't install, use github version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e3007c..df7f3c2 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ sudo pip install pybluez` You've installed the Python 2 version of the bluez bindings. Either run the script using python2 or install the Python 3 bindings. Since they aren't packaged, you would need to install them using pip: ``` -sudo python3 -m pip install pybluez` +sudo python3 -m pip install git+https://github.com/pybluez/pybluez.git` ``` ### Setup your Raspberry Pi From 3a789da26d70b4f2bf6ecfb9209d05637535c383 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 09:58:38 +0200 Subject: [PATCH 05/13] Handle better lack of 'bluetooth' device --- bleClient.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/bleClient.py b/bleClient.py index b879be0..cbbb163 100755 --- a/bleClient.py +++ b/bleClient.py @@ -52,12 +52,12 @@ def __init__(self, clientSocket=None): def getBluetoothServices(self): """Get BT service""" try: - logger.info("Searching for Bluetooth services ...") + logger.info("Searching for Bluetooth services ...") for reConnect in range(2, 4): bleService = find_service(uuid=self.uuid, address=self.addr) if len(bleService) == 0: logger.info( - "Re-connecting Bluetooth services : %d attempt", reConnect + "Re-connecting Bluetooth services : %d attempt", reConnect ) else: break @@ -80,6 +80,9 @@ def getBluetoothServices(self): "Couldn't find the RaspberryPi Bluetooth service : Invalid uuid", exc_info=True, ) + return False + + return True def getBluetoothSocket(self): """Get the BT socket""" @@ -181,7 +184,10 @@ def closeBluetoothSocket(self): def start(self): """Start the BT interface""" # Search for the RaspberryPi Bluetooth service - self.getBluetoothServices() + res = self.getBluetoothServices() + if not res: + logger.error("Failed to get bluetooth services") + sys.exit(0) # Create the client socket self.getBluetoothSocket() # Connect to bluetooth service From f044ebea98593cd828967b3eadf49fb281cd7e27 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 10:04:54 +0200 Subject: [PATCH 06/13] Fix code style and exception handling --- bleClient.py | 135 +++++++++++++++++++++++++-------------------------- 1 file changed, 65 insertions(+), 70 deletions(-) diff --git a/bleClient.py b/bleClient.py index cbbb163..e8847c0 100755 --- a/bleClient.py +++ b/bleClient.py @@ -4,6 +4,7 @@ # Auth: P Srinivas Rao # Desc: Bluetooth client application that uses RFCOMM sockets # intended for use with rfcomm-server +import sys import os import time import logging @@ -13,7 +14,7 @@ # import cPickle as pickle # Serializing and de-serializing a Python object structure import pickle -from bluetooth import * # Python Bluetooth library +import bluetooth # Python Bluetooth library logger = logging.getLogger("bleClientLogger") @@ -38,44 +39,44 @@ def startLogging( class bleClient: """Provide Bluetooth Client interface""" - def __init__(self, clientSocket=None): - if clientSocket is None: - self.clientSocket = clientSocket - self.bleService = None + def __init__(self, client_socket=None): + if client_socket is None: + self.client_socket = client_socket + self.ble_service = None self.addr = None self.uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" - self.jsonFile = "text.json" - self.jsonObj = None + self.json_file = "text.json" + self.json_obj = None else: - self.clientSocket = clientSocket + self.client_socket = client_socket def getBluetoothServices(self): """Get BT service""" try: logger.info("Searching for Bluetooth services ...") - for reConnect in range(2, 4): - bleService = find_service(uuid=self.uuid, address=self.addr) - if len(bleService) == 0: + for reconnect in range(2, 4): + ble_service = bluetooth.find_service(uuid=self.uuid, address=self.addr) + if len(ble_service) == 0: logger.info( - "Re-connecting Bluetooth services : %d attempt", reConnect + "Re-connecting Bluetooth services : %d attempt", reconnect ) else: break - if not bleService: + if not ble_service: raise Exception([SystemExit(), KeyboardInterrupt()]) else: logger.info("Found Bluetooth services ..") - logger.info("Protocol\t: %s", bleService[0]["protocol"]) - logger.info("Name\t\t: %s", bleService[0]["name"]) - logger.info("Service-id\t: %s", bleService[0]["service-id"]) - logger.info("Profiles\t: %s", bleService[0]["profiles"]) - logger.info("Service-class\t: %s", bleService[0]["service-classes"]) - logger.info("Host\t\t: %s", bleService[0]["host"]) - logger.info("Provider\t: %s", bleService[0]["provider"]) - logger.info("Port\t\t: %s", bleService[0]["port"]) - logger.info("Description\t: %s", bleService[0]["description"]) - self.bleService = bleService - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: + logger.info("Protocol\t: %s", ble_service[0]["protocol"]) + logger.info("Name\t\t: %s", ble_service[0]["name"]) + logger.info("Service-id\t: %s", ble_service[0]["service-id"]) + logger.info("Profiles\t: %s", ble_service[0]["profiles"]) + logger.info("Service-class\t: %s", ble_service[0]["service-classes"]) + logger.info("Host\t\t: %s", ble_service[0]["host"]) + logger.info("Provider\t: %s", ble_service[0]["provider"]) + logger.info("Port\t\t: %s", ble_service[0]["port"]) + logger.info("Description\t: %s", ble_service[0]["description"]) + self.ble_service = ble_service + except (Exception, bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error( "Couldn't find the RaspberryPi Bluetooth service : Invalid uuid", exc_info=True, @@ -87,86 +88,80 @@ def getBluetoothServices(self): def getBluetoothSocket(self): """Get the BT socket""" try: - self.clientSocket = BluetoothSocket(RFCOMM) + self.client_socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM) logger.info( - "Bluetooth client socket successfully created for RFCOMM service ..." + "Bluetooth client socket successfully created for RFCOMM service ... " ) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: + except (Exception, bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error( - "Failed to create the bluetooth client socket for RFCOMM service ... ", + "Failed to create the bluetooth client socket for RFCOMM service ... ", exc_info=True, ) def getBluetoothConnection(self): """Get the BT connection""" try: - bleServiceInfo = self.bleService[0] - logger.info( - 'Connecting to "%s" on %s with port %s' - % ( - bleServiceInfo["name"], - bleServiceInfo["host"], - bleServiceInfo["port"], - ) + ble_service_info = self.ble_service[0] + msg = 'Connecting to "%s" on %s with port %s' % ( + ble_service_info["name"], + ble_service_info["host"], + ble_service_info["port"], + ) + logger.info(msg) + self.client_socket.connect( + (ble_service_info["host"], ble_service_info["port"]) ) - self.clientSocket.connect((bleServiceInfo["host"], bleServiceInfo["port"])) - logger.info("Connected successfully to %s " % (bleServiceInfo["name"])) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: + logger.info("Connected successfully to %s " % (ble_service_info["name"])) + except (Exception, bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: + msg = f'Failed to connect to "{ble_service_info["name"]}" on address {ble_service_info["host"]} with port {ble_service_info["port"]}' logger.error( - 'Failed to connect to "%s" on address %s with port %s' - % ( - bleServiceInfo["name"], - bleServiceInfo["host"], - bleServiceInfo["port"], - ), + msg, exc_info=True, ) def readJsonFile(self): """Read JSON file""" try: - jsonFileObj = open(self.jsonFile, "r", encoding="utf-8") - logger.info("File successfully uploaded to %s" % (jsonFileObj)) - self.jsonObj = json.load(jsonFileObj) - logger.info( - "Content loaded successfully from the %s file" % (self.jsonFile) - ) - jsonFileObj.close() + json_file_obj = open(self.json_file, "r", encoding="utf-8") + msg = "File successfully uploaded to %s" % (json_file_obj) + logger.info(msg) + self.json_obj = json.load(json_file_obj) + msg = "Content loaded successfully from the %s file" % (self.json_file) + logger.info(msg) + json_file_obj.close() except (Exception, IOError) as _: - logger.error( - "Failed to load content from the %s" % (self.jsonFile), exc_info=True - ) + msg = "Failed to load content from the %s" % (self.json_file) + logger.error(msg, exc_info=True) def serializeData(self): """Serialize the data""" try: - serializedData = pickle.dumps(self.jsonObj) + serialized_data = pickle.dumps(self.json_obj) logger.info("Object successfully converted to a serialized string") - return serializedData + return serialized_data except (Exception, pickle.PicklingError) as _: logger.error( "Failed to convert json object to serialized string", exc_info=True ) - def sendData(self, _serializedData): + def sendData(self, _serialized_data): """Send data via BT""" try: logger.info("Sending data over bluetooth connection") - _serializedData = str(len(_serializedData)) + ":" + _serializedData - self.clientSocket.send(_serializedData) + _serialized_data = str(len(_serialized_data)) + ":" + _serialized_data + self.client_socket.send(_serialized_data) time.sleep(0.5) while True: - dataRecv = self.clientSocket.recv(1024) - if dataRecv in [ + data_recv = self.client_socket.recv(1024) + if data_recv in [ "EmptyBufferResend", "CorruptedBufferResend", "DelimiterMissingBufferResend", ]: - self.clientSocket.send(_serializedData) + self.client_socket.send(_serialized_data) time.sleep(0.5) - logger.info( - "%s : Re-sending data over bluetooth connection" % (dataRecv) - ) + msg = f"{data_recv} : Re-sending data over bluetooth connection" + logger.info(msg) else: break logger.info("Data sent successfully over bluetooth connection") @@ -176,9 +171,9 @@ def sendData(self, _serializedData): def closeBluetoothSocket(self): """Close BT socket""" try: - self.clientSocket.close() + self.client_socket.close() logger.info("Bluetooth client socket successfully closed ...") - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: + except (Exception, bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error("Failed to close the bluetooth client socket ", exc_info=True) def start(self): @@ -199,9 +194,9 @@ def send(self): # Load the contents from the file, which creates a new json object self.readJsonFile() # Convert the json object to a serialized string - serializedData = self.serializeData() + serialized_data = self.serializeData() # Sending data over bluetooth connection - self.sendData(serializedData) + self.sendData(serialized_data) def stop(self): """Stop the BT interface""" From cb8421a239902c51ae34dc2106cafd0b8bfceab9 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 10:10:36 +0200 Subject: [PATCH 07/13] Styling and python3 writing style --- bleClient.py | 28 +++++++++-- bleServer.py | 131 +++++++++++++++++++++++++++++---------------------- 2 files changed, 99 insertions(+), 60 deletions(-) diff --git a/bleClient.py b/bleClient.py index e8847c0..543b534 100755 --- a/bleClient.py +++ b/bleClient.py @@ -76,7 +76,12 @@ def getBluetoothServices(self): logger.info("Port\t\t: %s", ble_service[0]["port"]) logger.info("Description\t: %s", ble_service[0]["description"]) self.ble_service = ble_service - except (Exception, bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: logger.error( "Couldn't find the RaspberryPi Bluetooth service : Invalid uuid", exc_info=True, @@ -92,7 +97,12 @@ def getBluetoothSocket(self): logger.info( "Bluetooth client socket successfully created for RFCOMM service ... " ) - except (Exception, bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: logger.error( "Failed to create the bluetooth client socket for RFCOMM service ... ", exc_info=True, @@ -112,7 +122,12 @@ def getBluetoothConnection(self): (ble_service_info["host"], ble_service_info["port"]) ) logger.info("Connected successfully to %s " % (ble_service_info["name"])) - except (Exception, bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: msg = f'Failed to connect to "{ble_service_info["name"]}" on address {ble_service_info["host"]} with port {ble_service_info["port"]}' logger.error( msg, @@ -173,7 +188,12 @@ def closeBluetoothSocket(self): try: self.client_socket.close() logger.info("Bluetooth client socket successfully closed ...") - except (Exception, bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: logger.error("Failed to close the bluetooth client socket ", exc_info=True) def start(self): diff --git a/bleServer.py b/bleServer.py index f8e4a90..a5ce4a9 100755 --- a/bleServer.py +++ b/bleServer.py @@ -5,13 +5,11 @@ # Desc: Bluetooth server application that uses RFCOMM sockets import os -import sys -import time import logging import logging.config import json # Uses JSON package -import cPickle as pickle # Serializing and de-serializing a Python object structure -from bluetooth import * # Python Bluetooth library +import pickle # Serializing and de-serializing a Python object structure +import bluetooth # Python Bluetooth library logger = logging.getLogger("bleServerLogger") @@ -25,135 +23,156 @@ def startLogging( if value: path = value if os.path.exists(path): - with open(path, "rt") as f: - config = json.load(f) + with open(path, "rt", encoding="utf-8") as file_handle: + config = json.load(file_handle) logging.config.dictConfig(config) else: logging.basicConfig(level=default_level) class bleServer: - def __init__(self, serverSocket=None, clientSocket=None): - if serverSocket is None: - self.dataObj = None - self.serverSocket = serverSocket - self.clientSocket = clientSocket - self.serviceName = "BluetoothServices" - self.jsonFile = "text.json" + def __init__(self, server_socket=None, client_socket=None): + if server_socket is None: + self.data_obj = None + self.server_socket = server_socket + self.client_socket = client_socket + self.service_name = "BluetoothServices" + self.json_file = "text.json" self.uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" else: - self.serverSocket = serverSocket - self.clientSocket = clientSocket + self.server_socket = server_socket + self.client_socket = client_socket def getBluetoothSocket(self): try: - self.serverSocket = BluetoothSocket(RFCOMM) + self.server_socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM) logger.info( "Bluetooth server socket successfully created for RFCOMM service..." ) - except (BluetoothError, SystemExit, KeyboardInterrupt) as e: + except (bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error("Failed to create the bluetooth server socket ", exc_info=True) def getBluetoothConnection(self): try: - self.serverSocket.bind(("", PORT_ANY)) + self.server_socket.bind(("", bluetooth.PORT_ANY)) logger.info( "Bluetooth server socket bind successfully on host " " to PORT_ANY..." ) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: logger.error( "Failed to bind server socket on host to PORT_ANY ... ", exc_info=True ) try: - self.serverSocket.listen(1) + self.server_socket.listen(1) logger.info( "Bluetooth server socket put to listening mode successfully ..." ) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: logger.error( "Failed to put server socket to listening mode ... ", exc_info=True ) try: - port = self.serverSocket.getsockname()[1] + port = self.server_socket.getsockname()[1] logger.info("Waiting for connection on RFCOMM channel %d" % (port)) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error( "Failed to get connection on RFCOMM channel ... ", exc_info=True ) def advertiseBluetoothService(self): try: - advertise_service( - self.serverSocket, - self.serviceName, + bluetooth.advertise_service( + self.server_socket, + self.service_name, service_id=self.uuid, - service_classes=[self.uuid, SERIAL_PORT_CLASS], - profiles=[SERIAL_PORT_PROFILE], + service_classes=[self.uuid, bluetooth.SERIAL_PORT_CLASS], + profiles=[bluetooth.SERIAL_PORT_PROFILE], # protocols = [ OBEX_UUID ] ) - logger.info("%s advertised successfully ..." % (self.serviceName)) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + logger.info("%s advertised successfully ..." % (self.service_name)) + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: logger.error("Failed to advertise bluetooth services ... ", exc_info=True) def acceptBluetoothConnection(self): try: - self.clientSocket, clientInfo = self.serverSocket.accept() - logger.info("Accepted bluetooth connection from %s", clientInfo) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e: + self.client_socket, client_info = self.server_socket.accept() + logger.info("Accepted bluetooth connection from %s", client_info) + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: logger.error("Failed to accept bluetooth connection ... ", exc_info=True) def recvData(self): try: while True: - data = self.clientSocket.recv(1024) + data = self.client_socket.recv(1024) if not data: - self.clientSocket.send("EmptyBufferResend") + self.client_socket.send("EmptyBufferResend") # remove the length bytes from the front of buffer # leave any remaining bytes in the buffer! - dataSizeStr, ignored, data = data.partition(":") + dataSizeStr, _, data = data.partition(":") dataSize = int(dataSizeStr) if len(data) < dataSize: - self.clientSocket.send("CorruptedBufferResend") + self.client_socket.send("CorruptedBufferResend") else: - self.clientSocket.send("DataRecived") + self.client_socket.send("DataRecived") break logger.info("Data received successfully over bluetooth connection") return data - except (Exception, IOError, BluetoothError) as e: + except (Exception, IOError, bluetooth.BluetoothError) as _: pass - def deserializedData(self, _dataRecv): + def deserializedData(self, _data_recv): try: - self.dataObj = pickle.loads(_dataRecv) + self.data_obj = pickle.loads(_data_recv) logger.info("Serialized string converted successfully to object") - except (Exception, pickle.UnpicklingError) as e: + except (Exception, pickle.UnpicklingError) as _: logger.error("Failed to de-serialized string ... ", exc_info=True) def writeJsonFile(self): try: # Open a file for writing - jsonFileObj = open(self.jsonFile, "w") - logger.info( - "%s file successfully opened to %s" % (self.jsonFile, jsonFileObj) - ) + json_file_obj = open(self.json_file, "w", encoding="utf-8") + msg = "%s file successfully opened to %s" % (self.json_file, json_file_obj) + logger.info(msg) # Save the dictionary into this file # (the 'indent=4' is optional, but makes it more readable) - json.dump(self.dataObj, jsonFileObj, indent=4) - logger.info("Content dumped successfully to the %s file" % (self.jsonFile)) + json.dump(self.data_obj, json_file_obj, indent=4) + msg = "Content dumped successfully to the %s file" % (self.json_file) + logger.info(msg) # Close the file - jsonFileObj.close() - logger.info("%s file successfully closed" % (self.jsonFile)) - except (Exception, IOError) as e: + json_file_obj.close() + msg = "%s file successfully closed" % (self.json_file) + logger.info(msg) + except (Exception, IOError) as _: logger.error( "Failed to write json contents to the file ... ", exc_info=True ) def closeBluetoothSocket(self): try: - self.clientSocket.close() - self.serverSocket.close() + self.client_socket.close() + self.server_socket.close() logger.info("Bluetooth sockets successfully closed ...") - except (Exception, BluetoothError) as e: + except (Exception, bluetooth.BluetoothError) as _: logger.error("Failed to close the bluetooth sockets ", exc_info=True) def start(self): @@ -168,9 +187,9 @@ def start(self): def receive(self): # receive data - dataRecv = self.recvData() + data_recv = self.recvData() # de-serializing data - self.deserializedData(dataRecv) + self.deserializedData(data_recv) # Writing json object to the file self.writeJsonFile() From 1f9feda4bc74bcb91924133f0632b2fa23c11cc8 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 10:13:47 +0200 Subject: [PATCH 08/13] Error handling --- bleServer.py | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/bleServer.py b/bleServer.py index a5ce4a9..cb3b752 100755 --- a/bleServer.py +++ b/bleServer.py @@ -3,7 +3,7 @@ # File: bleServer.py # Auth: P Srinivas Rao # Desc: Bluetooth server application that uses RFCOMM sockets - +import sys import os import logging import logging.config @@ -51,6 +51,8 @@ def getBluetoothSocket(self): ) except (bluetooth.BluetoothError, SystemExit, KeyboardInterrupt) as _: logger.error("Failed to create the bluetooth server socket ", exc_info=True) + return False + return True def getBluetoothConnection(self): try: @@ -67,6 +69,8 @@ def getBluetoothConnection(self): logger.error( "Failed to bind server socket on host to PORT_ANY ... ", exc_info=True ) + return False + try: self.server_socket.listen(1) logger.info( @@ -81,15 +85,26 @@ def getBluetoothConnection(self): logger.error( "Failed to put server socket to listening mode ... ", exc_info=True ) + return False try: port = self.server_socket.getsockname()[1] - logger.info("Waiting for connection on RFCOMM channel %d" % (port)) - except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as _: + msg = "Waiting for connection on RFCOMM channel %d" % (port) + logger.info(msg) + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: logger.error( "Failed to get connection on RFCOMM channel ... ", exc_info=True ) + return False + + return True def advertiseBluetoothService(self): + """Advertise BT service""" try: bluetooth.advertise_service( self.server_socket, @@ -99,7 +114,8 @@ def advertiseBluetoothService(self): profiles=[bluetooth.SERIAL_PORT_PROFILE], # protocols = [ OBEX_UUID ] ) - logger.info("%s advertised successfully ..." % (self.service_name)) + msg = "%s advertised successfully ..." % (self.service_name) + logger.info(msg) except ( Exception, bluetooth.BluetoothError, @@ -107,6 +123,9 @@ def advertiseBluetoothService(self): KeyboardInterrupt, ) as _: logger.error("Failed to advertise bluetooth services ... ", exc_info=True) + return False + + return True def acceptBluetoothConnection(self): try: @@ -177,11 +196,17 @@ def closeBluetoothSocket(self): def start(self): # Create the server socket - self.getBluetoothSocket() + res = self.getBluetoothSocket() + if not res: + sys.exit(0) # get bluetooth connection to port # of the first available - self.getBluetoothConnection() + res = self.getBluetoothConnection() + if not res: + sys.exit(0) # advertising bluetooth services - self.advertiseBluetoothService() + res = self.advertiseBluetoothService() + if not res: + sys.exit(0) # Accepting bluetooth connection self.acceptBluetoothConnection() From d89bbe66d0930697845e857b17ab68b6af9d9bf4 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 11:24:21 +0200 Subject: [PATCH 09/13] More work on code --- bleServer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bleServer.py b/bleServer.py index cb3b752..a316bdd 100755 --- a/bleServer.py +++ b/bleServer.py @@ -58,7 +58,7 @@ def getBluetoothConnection(self): try: self.server_socket.bind(("", bluetooth.PORT_ANY)) logger.info( - "Bluetooth server socket bind successfully on host " " to PORT_ANY..." + "Bluetooth server socket bind successfully on host '' to PORT_ANY..." ) except ( Exception, @@ -147,6 +147,7 @@ def recvData(self): self.client_socket.send("EmptyBufferResend") # remove the length bytes from the front of buffer # leave any remaining bytes in the buffer! + print("Incoming data") dataSizeStr, _, data = data.partition(":") dataSize = int(dataSizeStr) if len(data) < dataSize: From 061b4728796cf72134eb6ba89b029dd96400fe2c Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 11:24:51 +0200 Subject: [PATCH 10/13] b':' and nonetype ignore --- bleServer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bleServer.py b/bleServer.py index a316bdd..04a5509 100755 --- a/bleServer.py +++ b/bleServer.py @@ -147,8 +147,7 @@ def recvData(self): self.client_socket.send("EmptyBufferResend") # remove the length bytes from the front of buffer # leave any remaining bytes in the buffer! - print("Incoming data") - dataSizeStr, _, data = data.partition(":") + dataSizeStr, _, data = data.partition(b":") dataSize = int(dataSizeStr) if len(data) < dataSize: self.client_socket.send("CorruptedBufferResend") @@ -214,6 +213,11 @@ def start(self): def receive(self): # receive data data_recv = self.recvData() + # print(f"{data_recv=}") + + if data_recv is None: + logger.error("Failed to handle incoming data") + return # de-serializing data self.deserializedData(data_recv) # Writing json object to the file From f6507e34ac8f9541ad9e93bb14058e3285391d3d Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 11:24:59 +0200 Subject: [PATCH 11/13] Retry connect --- bleClient.py | 74 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/bleClient.py b/bleClient.py index 543b534..86df3ad 100755 --- a/bleClient.py +++ b/bleClient.py @@ -110,29 +110,45 @@ def getBluetoothSocket(self): def getBluetoothConnection(self): """Get the BT connection""" - try: - ble_service_info = self.ble_service[0] - msg = 'Connecting to "%s" on %s with port %s' % ( - ble_service_info["name"], - ble_service_info["host"], - ble_service_info["port"], - ) - logger.info(msg) - self.client_socket.connect( - (ble_service_info["host"], ble_service_info["port"]) - ) - logger.info("Connected successfully to %s " % (ble_service_info["name"])) - except ( - Exception, - bluetooth.BluetoothError, - SystemExit, - KeyboardInterrupt, - ) as _: - msg = f'Failed to connect to "{ble_service_info["name"]}" on address {ble_service_info["host"]} with port {ble_service_info["port"]}' - logger.error( - msg, - exc_info=True, - ) + ble_service_info = self.ble_service[0] + msg = ( + f'Connecting to "{ble_service_info["name"]}" on ' + f'{ble_service_info["host"]} with port {ble_service_info["port"]}' + ) + logger.info(msg) + + attempt = 0 + # Retry a few times + while True: + attempt += 1 + + try: + self.client_socket.connect( + (ble_service_info["host"], ble_service_info["port"]) + ) + msg = f"Connected successfully to {ble_service_info['name']}" + logger.info(msg) + break + except ( + Exception, + bluetooth.BluetoothError, + SystemExit, + KeyboardInterrupt, + ) as _: + msg = ( + f'Failed to connect to "{ble_service_info["name"]}" on ' + f'address {ble_service_info["host"]} with port {ble_service_info["port"]}' + ) + logger.error( + msg, + exc_info=True, + ) + + time.sleep(1) + if attempt > 5: + return False + + return True def readJsonFile(self): """Read JSON file""" @@ -159,11 +175,14 @@ def serializeData(self): "Failed to convert json object to serialized string", exc_info=True ) - def sendData(self, _serialized_data): + def sendData(self, serialized_data): """Send data via BT""" try: logger.info("Sending data over bluetooth connection") - _serialized_data = str(len(_serialized_data)) + ":" + _serialized_data + _serialized_data = b"" + _serialized_data += len(serialized_data).to_bytes(2, "little") + _serialized_data += b":" + _serialized_data += serialized_data self.client_socket.send(_serialized_data) time.sleep(0.5) while True: @@ -206,7 +225,10 @@ def start(self): # Create the client socket self.getBluetoothSocket() # Connect to bluetooth service - self.getBluetoothConnection() + res = self.getBluetoothConnection() + if not res: + logger.error("Failed to get bluetooth connection") + sys.exit(0) def send(self): """Send content""" From f7f05eade27836a4939b8fc0b9558cecc3f73313 Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 11:32:22 +0200 Subject: [PATCH 12/13] Fix bytes handling --- bleServer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bleServer.py b/bleServer.py index 04a5509..f16efe9 100755 --- a/bleServer.py +++ b/bleServer.py @@ -147,9 +147,9 @@ def recvData(self): self.client_socket.send("EmptyBufferResend") # remove the length bytes from the front of buffer # leave any remaining bytes in the buffer! - dataSizeStr, _, data = data.partition(b":") - dataSize = int(dataSizeStr) - if len(data) < dataSize: + data_size_str, _, data = data.partition(b":") + data_size = int.from_bytes(data_size_str, "little") + if len(data) < data_size: self.client_socket.send("CorruptedBufferResend") else: self.client_socket.send("DataRecived") From 2ee246af1d9ddc1d6bd74dbf3c2510b499a236ae Mon Sep 17 00:00:00 2001 From: Noam Rathaus Date: Sun, 26 Feb 2023 11:32:29 +0200 Subject: [PATCH 13/13] Remove tick --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df7f3c2..ffa2b2f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ sudo pip install pybluez` You've installed the Python 2 version of the bluez bindings. Either run the script using python2 or install the Python 3 bindings. Since they aren't packaged, you would need to install them using pip: ``` -sudo python3 -m pip install git+https://github.com/pybluez/pybluez.git` +sudo python3 -m pip install git+https://github.com/pybluez/pybluez.git ``` ### Setup your Raspberry Pi