class BtServer(object): def __init__(self): super(BtServer, self).__init__() self.socket = BluetoothSocket(RFCOMM) self.client = {} def start(self): # empty host address means this machine self.socket.bind(("", PORT_ANY)) self.socket.listen(config['backlog']) self.port = self.socket.getsockname()[1] uuid = config['uuid'] advertise_service( self.socket, "Rewave Server", service_id=uuid, service_classes=[uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE] ) print('Waiting for connection on RFCOMM channel %d' % self.port) self.client['socket'], self.client['info'] = self.socket.accept() print("Accepted connection from ", self.client['info']) def kill(self): self.socket.close() def close_connection(self): self.client['socket'].close()
def main(): # Setup logging setup_logging() # We need to wait until Bluetooth init is done time.sleep(10) # Make device visible os.system("hciconfig hci0 piscan") # Create a new server socket using RFCOMM protocol server_sock = BluetoothSocket(RFCOMM) # Bind to any port server_sock.bind(("", PORT_ANY)) # Start listening server_sock.listen(1) # Get the port the server socket is listening port = server_sock.getsockname()[1] # The service UUID to advertise uuid = "7be1fcb3-5776-42fb-91fd-2ee7b5bbb86d" # Start advertising the service advertise_service(server_sock, "RaspiBtSrv", service_id=uuid, service_classes=[uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE]) # These are the operations the service supports # Feel free to add more operations = ["ping", "example"] # Main Bluetooth server loop while True: print("Waiting for connection on RFCOMM channel %d" % port) client_sock = None try: # This will block until we get a new connection client_sock, client_info = server_sock.accept() print("Accepted connection from ", client_info) # Read the data sent by the client data = client_sock.recv(1024) if len(data) == 0: break print("Received [%s]" % data) # Handle the request if data == "getop": response = "op:%s" % ",".join(operations) elif data == "ping": response = "msg:Pong" elif data == "example": response = "msg:This is an example" # Insert more here else: response = "msg:Not supported" client_sock.send(response) print("Sent back [%s]" % response) except IOError: pass except KeyboardInterrupt: if client_sock is not None: client_sock.close() server_sock.close() print("Server going down") break
def task(self): # Waiting until Bluetooth init is done time.sleep(self.wakeup_time) # Make device visible self.scm.set_bluetooth_visible() # Create a new server socket using RFCOMM protocol server_sock = BluetoothSocket(RFCOMM) # Bind to any port server_sock.bind(("", PORT_ANY)) # Start listening server_sock.listen(self.max_simultaneous_connections) # Get the port the server socket is listening port = server_sock.getsockname()[1] # Main bluetooth server loop while True: logger.info( 'Waiting for bluetooth connection on channel {}'.format(port)) client_sock = None try: # Block until we get a new connection client_sock, client_info = server_sock.accept() logger.info('Accepted connection from {}'.format(client_info)) # Read the data sent by the client command = client_sock.recv(1024) if len(command) == 0: continue logger.info('Received [{}]'.format(command)) # Handle the request response = self.handle_request(command) client_sock.send(response) logger.info('Sent back [{}]'.format(response)) except IOError: pass except KeyboardInterrupt: if client_sock is not None: client_sock.close() server_sock.close() logger.info('Bluetooth server going down') break
class BtServer(object): def __init__(self, socket=None): super(BtServer, self).__init__() self.socket = socket def start(self): print('start called') if not self.socket: print('non socket, creating one') self.socket = BluetoothSocket(RFCOMM) # empty host address means this machine self.socket.bind(("", PORT_ANY)) self.socket.listen(config['backlog']) advertise_service( self.socket, "Rewave Server", service_id=config['uuid'], service_classes=[config['uuid'], SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE] ) self.port = self.socket.getsockname()[1] # need port for ref. self.accept() def stop(self): print("server stop called") self.socket.close() try: self.client_socket.close() except AttributeError as e: # in case if no client is connected pass def recv(self, buffer=2048): print('recv called') try: return self.client_socket.recv(buffer).decode(encoding='UTF-8') except UnicodeDecodeError as e: # return raw if unable to unicode decode return self.client_socket.recv(buffer) def send(self, data): self.client_socket.send(data) def close_connection(self): print("close_connection called") self.client_socket.close() def accept(self): # blocking call print("accept Called. Waiting for connection on RFCOMM channel", self.port) self.client_socket = self.socket.accept()[0] # returns socket, name
def run_bt_server(account): """Adapted from: https://github.com/EnableTech/raspberry-bluetooth-demo""" import pdb pdb.set_trace() server_sock = BluetoothSocket(RFCOMM) server_sock.bind(("", PORT_ANY)) server_sock.listen(1) port = server_sock.getsockname()[1] print ("listening on port %d" % port) uuid = "1e0ca4ea-299d-4335-93eb-27fcfe7fa848" advertise_service( server_sock, "Mock Detector", service_id=uuid, service_classes=[uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE], # protocols=[OBEX_UUID], ) print("Waiting for connection on RFCOMM channel %d" % port) client_sock, client_info = server_sock.accept() print("Accepted connection from ", client_info) try: while True: data = client_sock.recv(1024) if len(data) == 0: break print("received [%s]" % data) if data == b'ETH_ADDRESS\r\n': client_sock.send( "ETH_ADDRESS::0x{}\r\nEND\r\n".format(account.address()) ) elif data.startswith('SIGNED_MESSAGE::'): start = len('SIGNED_MESSAGE::') user_address = data[start:start+42] message = account.create_signed_message( user_address, int(time.time()) ) client_sock.send(message) except IOError: pass print("disconnected") client_sock.close() server_sock.close() print("all done")
def start_service(self, port, name, uuid, service_classes, service_profiles, provider, description, protocols): socket = BluetoothSocket(RFCOMM) socket.bind((self.address, port)) socket.listen(1) advertise_service(socket, name, uuid, service_classes, service_profiles, provider, description, protocols) print("Starting server for %s on port %i" % socket.getsockname()) #self.serve(socket) return socket
def _create_server(self): server_sock = BluetoothSocket(bt.RFCOMM) server_sock.bind(("", bt.PORT_ANY)) server_sock.listen(1) self.channel = server_sock.getsockname()[1] bt.advertise_service(server_sock, self.name, service_classes=[self.uuid], profiles=[]) return server_sock
class BlueComm: def __init__(self): self.stop = False self.exit = False def start(self, callback): self.stop = False self.server_sock = BluetoothSocket(RFCOMM) self.server_sock.bind(("", PORT_ANY)) self.server_sock.listen(1) port = self.server_sock.getsockname()[1] uuid = "fa87c0d0-afac-11de-8a39-0800200c9a66" advertise_service(self.server_sock, "blueCommServer", service_id=uuid, service_classes=[uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE] # protocols = [ OBEX_UUID ] ) print("Waiting for connection on RFCOMM channel %d" % port) self.client_sock, self.client_info = self.server_sock.accept() print("Accepted connection from ", self.client_info) try: while not self.stop: data = self.client_sock.recv(1024) if len(data) == 0: break callback(self, data) except IOError: pass print("disconnected") self.disconnect() def disconnect(self): self.client_sock.close() self.server_sock.close()
from json import loads # End standard library imports. # Start third party imports. from bluetooth import PORT_ANY, RFCOMM, SERIAL_PORT_CLASS, SERIAL_PORT_PROFILE, BluetoothSocket, advertise_service from socketio import Client # End third party imports. # Start project imports. # End project imports. CLIENT_OBJ = Client() BLUETOOTH_SOCKET_OBJ = BluetoothSocket(RFCOMM) BLUETOOTH_SOCKET_OBJ.bind((str(), PORT_ANY)) BLUETOOTH_SOCKET_OBJ.listen(1) PORT_INT = BLUETOOTH_SOCKET_OBJ.getsockname()[1] UUID_STR = '94f39d29-7d6d-437d-973b-fba39e49d4ee' def get_json_from_socket(socketObj) -> dict: """" """ receiveBytes = socketObj.recv(1024) if len(receiveBytes) == 0: print("Received 0 bytes") return None return loads(receiveBytes.decode('utf-8')) def main() -> None: """
class BluetoothInterface(BaseInterface): """The Bluetooth interface definition for communication with wireless client devices.""" __interface_name__ = 'bluetooth' def __init__(self, controller): """ Initializes a bluetooth service that may be consumed by a remote client. Arguments --------- controller : controllers.base.BaseController the parent controller that is instantiated this interface """ super(BluetoothInterface, self).__init__() self.controller = controller self.client_sock = None self.client_info = None self.rfcomm_channel = None self.service_name = self.get_setting('service_name') self.service_uuid = self.get_setting('service_uuid') self.server_sock = None self.thread = None def connect(self): """Creates a new thread that listens for an incoming bluetooth RFCOMM connection.""" LOGGER.info('creating thread for bluetooth interface...') self.thread = threading.Thread(target=self.listen_for_rfcomm_connection) self.thread.daemon = True self.thread.start() def listen_for_rfcomm_connection(self): """ Starts bluetooth interfaces """ # prepare bluetooth server self.server_sock = BluetoothSocket(RFCOMM) self.server_sock.bind(("", PORT_ANY)) self.server_sock.listen(1) self.rfcomm_channel = self.server_sock.getsockname()[1] # start listening for incoming connections try: advertise_service( sock=self.server_sock, name=self.service_name, service_id=self.service_uuid, service_classes=[self.service_uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE] ) except: LOGGER.exception("[ERROR] failed to advertise service") return LOGGER.info('waiting for connection on RFCOMM channel %d', self.rfcomm_channel) # accept received connection self.client_sock, self.client_info = self.server_sock.accept() self.state = self.__states__.STATE_CONNECTED LOGGER.info('accepted connection from %r', self.client_info) # start listening for data self.consume_bus() def disconnect(self): """ Closes Bluetooth connection and resets handle """ LOGGER.info('destroying bluetooth interface...') self.state = self.__states__.STATE_DISCONNECTING if self.client_sock and hasattr(self.client_sock, 'close'): self.client_sock.close() self.client_sock = None if self.server_sock and hasattr(self.server_sock, 'close'): self.server_sock.close() self.server_sock = None # reset the bluetooth interface self.thread = None self.perform_hci0_reset() self.state = self.__states__.STATE_READY @staticmethod def perform_hci0_reset(): """Resets the bluetooth hci0 device via hciconfig command line interface.""" try: LOGGER.info('performing hci0 down/up...') subprocess.Popen('hciconfig hci0 down', shell=True).communicate() subprocess.Popen('hciconfig hci0 up', shell=True).communicate() LOGGER.info('hci0 down/up has completed') except Exception as exception: LOGGER.exception("Failed to restart hci0 - %r", exception) def receive(self, data): """ Processes received data from Bluetooth socket Arguments --------- data : basestring the data received from the bluetooth connection """ try: packet = json.loads(data.decode('utf-8')) LOGGER.info('received packet via bluetooth: %r', packet['data']) # invoke bound method (if set) if self.receive_hook and hasattr(self.receive_hook, '__call__'): self.receive_hook(packet['data']) except Exception as exception: LOGGER.exception('error: %r', exception) def send(self, data): """ Sends data via Bluetooth socket connection Arguments --------- data : basestring the data to be sent via this interface """ if self.state != self.__states__.STATE_CONNECTED: LOGGER.error('error: send() was called but state is not connected') return False try: LOGGER.info('sending IBUSPacket(s)...') packets = [] for packet in data: packets.append(packet.as_serializable_dict()) # encapsulate ibus packets and send data = {"data": json.dumps(packets)} # TODO : is an inner json.dumps necessary? LOGGER.info(data) self.client_sock.send(json.dumps(data)) except Exception: # socket was closed, graceful restart LOGGER.exception('bluetooth send exception') self.reconnect() def consume_bus(self): """ Start listening for incoming data """ try: LOGGER.info('starting to listen for bluetooth data...') read_buffer_length = self.get_setting('read_buffer_length', int) while self.client_sock: data = self.client_sock.recv(read_buffer_length) if len(data) > 0: self.receive(data) except Exception as exception: LOGGER.exception('android device was disconnected - %r', exception) self.reconnect()
def main(): """ Main method of the application. Must be run with superuser permissions. Params: <user> <network_interface> <hotspot_ssid> <hotspot_password> Creates the Bluetooth server and starts listening to clients. """ GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(29, GPIO.OUT) GPIO.output(29, GPIO.HIGH) GPIO.setup(15, GPIO.IN, pull_up_down=GPIO.PUD_UP) Thread(target=button_thread).start() signal.signal(signal.SIGINT, signal_handler) global net_interface global wifi_on global hotspot_enabled global hotspot_ssid global hotspot_pswd global server_sock global client_sock global username global type_pswd global indiweb global led_thread_run global config_file if len(sys.argv) == 5: username = sys.argv[1] print("Username = "******"Network interface = " + net_interface) hotspot_ssid = sys.argv[3] print("Hotspot SSID = " + hotspot_ssid) hotspot_pswd = sys.argv[4] print("Hotspot Password = "******"b9029ed0-6d6a-4ff6-b318-215067a6d8b1" print("BT service UUID = " + uuid) config_file = "{0}.{1}".format("/home" + username + "/", "Telescope-Pi.ini") if username == "root": if os.path.isdir("/home/pi/"): config_file = "/home/pi/.Telescope-Pi.ini" else: config_file = None print("Error! Invalid user!") print("Running in emergency mode!") emergency_mode_led() config = configparser.ConfigParser() if os.path.exists(config_file) and os.path.isfile(config_file): config.read(config_file) if "Wi-Fi" in config and config["Wi-Fi"] == "yes": turn_on_wifi() try: if len(Cell.all(net_interface)) == 0: print("No Wi-Fi networks found, starting hotspot.") start_hotspot() except InterfaceError as e: print("An error occurred while scanning Wi-Fi network!") print(str(e)) if hotspot_enabled is False and "Hotspot" in config and config["Hotspot"] == "yes": start_hotspot() if "INDI" in config and config["INDI"] == "yes": indiweb_start() else: turn_on_wifi() try: if len(list(Cell.all(net_interface))) == 0: print("No Wi-Fi networks found, starting hotspot.") start_hotspot() except InterfaceError as e: print("An error occurred while scanning Wi-Fi network!") print(str(e)) indiweb_start() try: server_sock = BluetoothSocket(RFCOMM) server_sock.bind(("", PORT_ANY)) server_sock.listen(1) port = server_sock.getsockname()[1] advertise_service(server_sock, "Telescope-Pi", service_id=uuid, service_classes=[ uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE]) Thread(target=led_thread).start() while True: print("Waiting for connection on RFCOMM channel %d" % port) led_thread_run = True client_sock, client_info = server_sock.accept() led_thread_run = False print("Accepted connection from " + str(client_info)) bt_send("NetInterface=" + net_interface + "\nWiFi=" + str(wifi_on) + "\nHotspot=" + str(hotspot_enabled) + "\nHotspotSSID=" + hotspot_ssid + "\nHotspotPswdType=WPA\nHotspotPswd=" + hotspot_pswd + "\nINDI=" + str(indiweb is not None)) send_ip() try: while True: data = client_sock.recv(1024) if len(data) == 0: break for line in data.decode().splitlines(): parse_rfcomm(line.strip()) except Exception as e: print(str(e)) print("Disconnected") client_sock.close() client_sock = None type_pswd = False except BluetoothError as e: print("No Bluetooth adapter found! Make sure the systemd service has \"Type=idle\".") print("Error message: " + str(e)) print("Running in emergency mode!") emergency_mode_led() else: print("Usage: \"sudo python hotspot-controller-bluetooth.py" + "<user> <network_interface> <hotspot_ssid> <hotspot_password>\"") print("Running in emergency mode!") emergency_mode_led()
class BluetoothOffer: def __init__(self, key, port=3, size=1024): self.key = key self.port = port self.size = size self.server_socket = None self.message_def = None self.stopped = False self.code = None @inlineCallbacks def start(self): self.stopped = False message = "Back" success = False try: while not self.stopped and not success: # server_socket.accept() is not stoppable. So with select we can call accept() # only when we are sure that there is already a waiting connection ready_to_read, ready_to_write, in_error = yield threads.deferToThread( select.select, [self.server_socket], [], [], 0.5) if ready_to_read: # We are sure that a connection is available, so we can call # accept() without deferring it to a thread client_socket, address = self.server_socket.accept() key_data = get_public_key_data(self.key.fingerprint) kd_decoded = key_data.decode('utf-8') yield threads.deferToThread(client_socket.sendall, kd_decoded) log.info("Key has been sent") client_socket.shutdown(socket.SHUT_RDWR) client_socket.close() success = True message = None except Exception as e: log.error("An error occurred: %s" % e) success = False message = e returnValue((success, message)) def allocate_code(self): try: code = get_local_bt_address().upper() except dbus.exceptions.DBusException as e: if e.get_dbus_name() == "org.freedesktop.systemd1.NoSuchUnit": log.info("No Bluetooth devices found, probably the bluetooth service is not running") elif e.get_dbus_name() == "org.freedesktop.DBus.Error.UnknownObject": log.info("No Bluetooth devices available") else: log.error("An unexpected error occurred %s", e.get_dbus_name()) self.code = None return None if self.server_socket is None: self.server_socket = BluetoothSocket(RFCOMM) # We can also bind only the mac found with get_local_bt_address(), anyway # even with multiple bt in a single system BDADDR_ANY is not a problem self.server_socket.bind((socket.BDADDR_ANY, PORT_ANY)) # Number of unaccepted connections that the system will allow before refusing new connections backlog = 1 self.server_socket.listen(backlog) log.info("sockname: %r", self.server_socket.getsockname()) port = self.server_socket.getsockname()[1] log.info("BT Code: %s %s", code, port) bt_data = "BT={0};PT={1}".format(code, port) return bt_data def stop(self): log.debug("Stopping bt receive") self.stopped = True if self.server_socket: self.server_socket.shutdown(socket.SHUT_RDWR) self.server_socket.close() self.server_socket = None
class BluetoothOffer: def __init__(self, key, port=3, size=1024): self.key = key self.port = port self.size = size self.server_socket = None self.message_def = None self.stopped = False @inlineCallbacks def start(self): self.stopped = False message = "Back" success = False try: while not self.stopped and not success: # server_socket.accept() is not stoppable. So with select we can call accept() # only when we are sure that there is already a waiting connection ready_to_read, ready_to_write, in_error = yield threads.deferToThread( select.select, [self.server_socket], [], [], 0.5) if ready_to_read: # We are sure that a connection is available, so we can call # accept() without deferring it to a thread client_socket, address = self.server_socket.accept() key_data = get_public_key_data(self.key.fingerprint) kd_decoded = key_data.decode('utf-8') yield threads.deferToThread(client_socket.sendall, kd_decoded) log.info("Key has been sent") client_socket.shutdown(socket.SHUT_RDWR) client_socket.close() success = True message = None except Exception as e: log.error("An error occurred: %s" % e) success = False message = e returnValue((success, message)) def allocate_code(self): """Acquires and returns a string suitable for finding the key via Bluetooth. Returns None if no powered on adapter could be found.""" # TODO: when we have magic-wormhole we should perform this operation in async # and show the loading spinning wheel bt_data = None try: code = get_local_bt_address().upper() except NoBluezDbus as e: log.debug("Bluetooth service seems to be unavailable: %s", e) except NoAdapter as e: log.debug("Bluetooth adapter is not available: %s", e) except UnpoweredAdapter as e: log.debug("Bluetooth adapter is turned off: %s", e) else: if self.server_socket is None: self.server_socket = BluetoothSocket(RFCOMM) # We create a bind with the Bluetooth address we have in the system self.server_socket.bind((code, PORT_ANY)) # Number of unaccepted connections that the system will allow before refusing new connections backlog = 1 self.server_socket.listen(backlog) log.info("sockname: %r", self.server_socket.getsockname()) port = self.server_socket.getsockname()[1] log.info("BT Code: %s %s", code, port) bt_data = "BT={0};PT={1}".format(code, port) return bt_data def stop(self): log.debug("Stopping bt receive") self.stopped = True if self.server_socket: self.server_socket.shutdown(socket.SHUT_RDWR) self.server_socket.close() self.server_socket = None
class BluetoothInterface(BaseInterface): """The Bluetooth interface definition for communication with wireless client devices.""" __interface_name__ = 'bluetooth' def __init__(self, controller): """ Initializes a bluetooth service that may be consumed by a remote client. Arguments --------- controller : controllers.base.BaseController the parent controller that is instantiated this interface """ super(BluetoothInterface, self).__init__() self.controller = controller self.client_sock = None self.client_info = None self.rfcomm_channel = None self.service_name = self.get_setting('service_name') self.service_uuid = self.get_setting('service_uuid') self.server_sock = None self.thread = None def connect(self): """Creates a new thread that listens for an incoming bluetooth RFCOMM connection.""" LOGGER.info('creating thread for bluetooth interface...') self.thread = threading.Thread( target=self.listen_for_rfcomm_connection) self.thread.daemon = True self.thread.start() def listen_for_rfcomm_connection(self): """ Starts bluetooth interfaces """ # prepare bluetooth server self.server_sock = BluetoothSocket(RFCOMM) self.server_sock.bind(("", PORT_ANY)) self.server_sock.listen(1) self.rfcomm_channel = self.server_sock.getsockname()[1] # start listening for incoming connections advertise_service( self.server_sock, self.service_name, service_id=self.service_uuid, service_classes=[self.service_uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE]) LOGGER.info('waiting for connection on RFCOMM channel %d' % self.rfcomm_channel) # accept received connection self.client_sock, self.client_info = self.server_sock.accept() self.state = self.__states__.STATE_CONNECTED LOGGER.info('accepted connection from %r', self.client_info) # start listening for data self.consume_bus() def disconnect(self): """ Closes Bluetooth connection and resets handle """ LOGGER.info('destroying bluetooth interface...') self.state = self.__states__.STATE_DISCONNECTING if self.client_sock and hasattr(self.client_sock, 'close'): self.client_sock.close() self.client_sock = None if self.server_sock and hasattr(self.server_sock, 'close'): self.server_sock.close() self.server_sock = None # reset the bluetooth interface self.thread = None self.perform_hci0_reset() self.state = self.__states__.STATE_READY @staticmethod def perform_hci0_reset(): """Resets the bluetooth hci0 device via hciconfig command line interface.""" try: LOGGER.info('performing hci0 down/up...') subprocess.Popen('sudo hciconfig hci0 down', shell=True).communicate() subprocess.Popen('sudo hciconfig hci0 up', shell=True).communicate() LOGGER.info('hci0 down/up has completed') except Exception as exception: LOGGER.exception("Failed to restart hci0 - %r", exception) def receive(self, data): """ Processes received data from Bluetooth socket Arguments --------- data : basestring the data received from the bluetooth connection """ try: packet = json.loads(data) LOGGER.info('received packet via bluetooth: %r', packet['data']) # invoke bound method (if set) if self.receive_hook and hasattr(self.receive_hook, '__call__'): self.receive_hook(packet['data'].decode('hex')) except Exception as exception: LOGGER.exception('error: %r', exception) def send(self, data): """ Sends data via Bluetooth socket connection Arguments --------- data : basestring the data to be sent via this interface """ if self.state != self.__states__.STATE_CONNECTED: LOGGER.error('error: send() was called but state is not connected') return False try: LOGGER.info('sending IBUSPacket(s)...') packets = [] for packet in data: packets.append(packet.as_serializable_dict()) # encapsulate ibus packets and send data = { "data": json.dumps(packets) } # TODO : is an inner json.dumps necessary? LOGGER.info(data) self.client_sock.send(json.dumps(data)) except Exception as exception: # socket was closed, graceful restart LOGGER.exception('bt send: %r', exception.message) self.reconnect() def consume_bus(self): """ Start listening for incoming data """ try: LOGGER.info('starting to listen for bluetooth data...') read_buffer_length = self.get_setting('read_buffer_length', int) while self.client_sock: data = self.client_sock.recv(read_buffer_length) if len(data) > 0: self.receive(data) except Exception as exception: LOGGER.exception('android device was disconnected - %r', exception) self.reconnect()
class BluetoothConn(ServerInterface): def __init__(self, config: ProjectConfig): self.conn = None self.client = None self._connected = False self.config = config self.address = self.config.get('BT_ADDRESS') self.port = int(self.config.get('BT_PORT')) def get_name(self) -> str: return format( f'Bluetooth connection on {self.address} port {self.port}') def get_tags(self) -> dict: return {'ANDROID': True, 'BT': True} def is_connected(self) -> bool: return self._connected def connect(self): try: self.conn = BluetoothSocket( bluetooth.RFCOMM) # use RFCOMM protocol self.conn.bind( (self.address, self.port)) # empty address; use any available adapter self.address, self.port = self.conn.getsockname() self.conn.listen(1) uuid = self.config.get('BT_UUID') bluetooth.advertise_service( sock=self.conn, name='MDP-Group-15-Bluetooth-Server', service_id=uuid, service_classes=[uuid, bluetooth.SERIAL_PORT_CLASS], profiles=[bluetooth.SERIAL_PORT_PROFILE], ) print( f'Listening for Bluetooth connection on {self.address} port {self.port}' ) self.client, client_info = self.conn.accept() print(f'Connected to {client_info}') self._connected = True except Exception as e: print(f'Error with {self.get_name()}: {e}') self.disconnect() raise ConnectionError def read(self): try: data = self.client.recv(1024) # data = data.decode('utf-8') if not data: raise ConnectionError('No transmission') data_dict = json.loads(data) print(f'Received from Android device: {data}') return self.format_data(data_dict) except Exception as e: print(f'Error with reading from {self.get_name()}: {e}') #print('Reconnecting...') #self.disconnect() #raise ConnectionError def write(self, message): try: json_str = json.dumps(message) byte_msg = bytes(json_str, encoding='utf-8') self.client.send(byte_msg) print(f'Sent to Android device: {byte_msg}') except Exception as e: print(f'Error with writing {message} to {self.get_name()}: {e}') #print('Reconnecting...') #self.disconnect() raise ConnectionError def disconnect(self): if self.conn: self.conn.close() print('Terminating server socket..') if self.client: self.client.close() print('Terminating client socket..') self._connected = False
#!/usr/bin/env python3 from bluetooth import BluetoothSocket, RFCOMM, PORT_ANY, advertise_service, SERIAL_PORT_CLASS, SERIAL_PORT_PROFILE server_sock = BluetoothSocket(RFCOMM) server_sock.bind(("", PORT_ANY)) server_sock.listen(1) port = server_sock.getsockname()[1] uuid = "a140ff7b-6539-40fe-9481-671108c144d6" advertise_service(server_sock, "PenPi Service", uuid) print("Waiting for connection on RFCOMM channel %d" % port) client_sock, client_info = server_sock.accept() print("Accepted connection from ", client_info) try: while True: data = client_sock.recv(1024) if len(data) == 0: break print("received [%s]" % data) except IOError: pass print("disconnected") client_sock.close()
def launch_hub_bluetooth_server(config_file_path): ''' Launches the Tremium Hub bluetooth server which the Tremium Nodes connect to. Parameters ---------- config_file_path (str) : path to the hub configuration file ''' # loading Tremium Hub configurations config_manager = HubConfigurationManager(config_file_path) log_file_path = os.path.join( config_manager.config_data["hub-file-transfer-dir"], config_manager.config_data["bluetooth-server-log-name"]) # setting up logging logger = logging.getLogger() logger.setLevel(logging.INFO) log_handler = logging.handlers.WatchedFileHandler(log_file_path) log_handler.setFormatter( logging.Formatter('%(name)s - %(levelname)s - %(message)s')) logger.addHandler(log_handler) # defining container for connection handler handles connection_handlers_h = [] try: # creating socket to listen for new connections listener_s = BluetoothSocket() listener_s.bind( (config_manager.config_data["bluetooth-adapter-mac-server"], config_manager.config_data["bluetooth-port"])) listener_s.listen(1) # advertising the listenning connection advertise_service(listener_s, config_manager.config_data["hub-id"]) bind_address = listener_s.getsockname() time_str = datetime.datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d_%H-%M-%S') logging.info( "{0} - Hub Bluetooth server listening on address : {1}".format( time_str, bind_address)) except Exception as e: time_str = datetime.datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d_%H-%M-%S') logging.error( "{0} - Hub Bluetooth server failed to create listener socket : {1}" .format(time_str, e)) raise while True: try: # blocking until a new connection occurs, then create connection handler client_s, remote_address = listener_s.accept() client_s.settimeout( config_manager.config_data["bluetooth-comm-timeout"]) connection_handler = HubServerConnectionHandler( config_file_path, client_s, remote_address) # launching connection handler in a seperate process process_h = Process(target=connection_handler.handle_connection, args=()) process_h.start() connection_handlers_h.append(process_h) time_str = datetime.datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d_%H-%M-%S') logging.info( "{0} - Hub Bluetooth server accepted and is handling connection from remote : {1}\ ".format(time_str, remote_address)) #regular check to clear dead handles for handler_h in connection_handlers_h: if handler_h is not None: connection_handlers_h.remove(handler_h) except Exception as e: # killing all connection handler processes still running for handler_h in connection_handlers_h: if handler_h.exitcode is None: handler_h.terminate() time_str = datetime.datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d_%H-%M-%S') logging.error( "{0} - Hub Bluetooth server failed to handle incoming connection : {1}" .format(time_str, e)) raise
def run_bt_server(end_event, device_name, account): """Adapted from: https://github.com/EnableTech/raspberry-bluetooth-demo""" server_sock = BluetoothSocket(RFCOMM) server_sock.bind(("", PORT_ANY)) server_sock.listen(1) port = server_sock.getsockname()[1] print("listening on port %d" % port) uuid = "1e0ca4ea-299d-4335-93eb-27fcfe7fa848" try: advertise_service( server_sock, device_name, service_id=uuid, service_classes=[uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE], # protocols=[OBEX_UUID], ) except BluetoothError as e: print('ERROR: Bluetooth Error:{}.\n Quiting bluetooth server. Is your ' 'bluetooth setup correctly? Do you have sudo privileges?'.format( e)) return print("Waiting for connection on RFCOMM channel %d" % port) client_sock, client_info = server_sock.accept() print("Accepted connection from ", client_info) client_sock.setblocking(0) bufferdata = bytearray() try: while not end_event.is_set(): ready = select.select([client_sock], [], [], 5) if not ready[0]: break data = client_sock.recv(1024) if len(data) == 0: break print("received [%s]" % data) bufferdata = bufferdata + data print(bufferdata) try: end = bufferdata.index(b'\n') our_data = bufferdata[0:end].strip(b'\r') if len(bufferdata) > end: bufferdata = bufferdata[end + 1:] else: bufferdata = bytearray() bluetooth_process(our_data, client_sock, account) except ValueError: pass except IOError: pass print("bluetooth server disconnected") client_sock.close() server_sock.close() print("all done")