Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
venv/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
245 changes: 172 additions & 73 deletions bleClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,151 +4,250 @@
# Auth: P Srinivas Rao
# Desc: Bluetooth client application that uses RFCOMM sockets
# intended for use with rfcomm-server
import os
import sys
import os
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
import pickle

import bluetooth # 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
"""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:
def __init__(self, clientSocket=None):
if clientSocket is None:
self.clientSocket = clientSocket
self.bleService = None
"""Provide Bluetooth Client interface"""

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:
logger.info("Re-connecting Bluetooth services : %d attempt", reConnect)
logger.info("Searching for Bluetooth services ...")
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
)
else:
break
if not bleService: raise SystemExit(), KeyboardInterrupt()
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 e:
logger.error("Couldn't find the RaspberryPi Bluetooth service : Invalid uuid", exc_info=True)
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,
)
return False

return 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:
logger.error("Failed to create the bluetooth client socket for RFCOMM service ... ", exc_info=True)
self.client_socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
logger.info(
"Bluetooth client socket successfully created for RFCOMM service ... "
)
except (
Exception,
bluetooth.BluetoothError,
SystemExit,
KeyboardInterrupt,
) as _:
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']))
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)
"""Get the BT connection"""
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"""
try:
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))
jsonFileObj.close()
except (Exception, IOError) as e:
logger.error("Failed to load content from the %s" % (self.jsonFile), exc_info=True)
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 _:
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
except (Exception, pickle.PicklingError) as e:
logger.error("Failed to convert json object to serialized string", exc_info=True)
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 = 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:
dataRecv= self.clientSocket.recv(1024)
if dataRecv in ['EmptyBufferResend', 'CorruptedBufferResend', 'DelimiterMissingBufferResend']:
self.clientSocket.send(_serializedData)
data_recv = self.client_socket.recv(1024)
if data_recv in [
"EmptyBufferResend",
"CorruptedBufferResend",
"DelimiterMissingBufferResend",
]:
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")
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()
self.client_socket.close()
logger.info("Bluetooth client socket successfully closed ...")
except (Exception, BluetoothError, SystemExit, KeyboardInterrupt) as e:
except (
Exception,
bluetooth.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()
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
self.getBluetoothConnection()
res = self.getBluetoothConnection()
if not res:
logger.error("Failed to get bluetooth connection")
sys.exit(0)

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
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"""

# Disconnecting bluetooth service
self.closeBluetoothSocket()

if __name__ == '__main__':

if __name__ == "__main__":
startLogging()
logger.info("Setup logging configuration")
bleClnt = bleClient()
Expand Down
Loading