Esempio n. 1
0
 def call(self, *commands):
     '''
     Helper function that implements a (subset of) the RESP
     protocol used by Redis >= 1.2
     '''
     cm = context.get_context().connection_mgr
     sock = BufferedSocket(cm.get_connection(self.address))
     # ARRAY: first byte *, decimal length, \r\n, contents
     out = ['*' + str(len(commands))] + \
         ["${0}\r\n{1}".format(len(e), e) for e in commands]
     out = "\r\n".join(out) + "\r\n"
     sock.send(out)
     fbyte = sock.peek(1)
     if fbyte == "-":  # error string
         raise RedisError(sock.recv_until('\r\n'))
     elif fbyte == '+':  # simple string
         resp = sock.recv_until('\r\n')[1:]
     elif fbyte == '$':  # bulk string
         length = int(sock.recv_until('\r\n')[1:])
         if length == -1:
             resp = None
         else:
             resp = sock.recv_size(length)
     cm.release_connection(sock)
     return resp
Esempio n. 2
0
 def handle_client(self, sock, addr):
     'Make sockets available to next process.'
     bsock = BufferedSocket(sock)
     secret = bsock.recv_size(len(self.secret))
     if secret != self.secret:
         bsock.send('BAD SECRET.')
         sock.close()
         return
     send_socks = []
     for server_sock in self.sockets.values():
         if sock.getsockname() == server_sock.getsockname():
             continue  # exclude the socket-passing-socket
         send_socks.append(server_sock)
     sock.send(str(len(send_socks)) + '.')
     for server_sock in send_socks:
         sendfileobj.sendfileobj(sock, server_sock)
     sock.close()
Esempio n. 3
0
class BlueToothGateway(BanyanBase, threading.Thread):
    """
    This class implements Bluetooth an RFCOMM server or client,
    configurable from command line options.

    usage: bluetooth_gateway.py [-h] [-a SERVER_BT_ADDRESS]
                            [-b BACK_PLANE_IP_ADDRESS] [-g GATEWAY_TYPE]
                            [-j JSON_DATA] [-l PUBLISH_TOPIC]
                            [-m SUBSCRIBER_LIST [SUBSCRIBER_LIST ...]]
                            [-n PROCESS_NAME] [-p PUBLISHER_PORT]
                            [-s SUBSCRIBER_PORT] [-t LOOP_TIME] [-u UUID]

        optional arguments:
          -h, --help            show this help message and exit
          -a SERVER_BT_ADDRESS  Bluetooth MAC Address of Bluetooth Gateway
          -b BACK_PLANE_IP_ADDRESS
                                None or IP address used by Back Plane
          -g GATEWAY_TYPE       Type of Gateway : server or client
          -j JSON_DATA          Bluetooth packets json encoded True or False
          -l PUBLISH_TOPIC      Banyan publisher topic
          -m SUBSCRIBER_LIST [SUBSCRIBER_LIST ...]
                                Banyan topics space delimited: topic1 topic2 topic3
          -n PROCESS_NAME       Set process name in banner
          -p PUBLISHER_PORT     Publisher IP port
          -s SUBSCRIBER_PORT    Subscriber IP port
          -t LOOP_TIME          Event Loop Timer in seconds
          -u UUID               Bluetooth UUID

    """

    # gateway types
    BTG_SERVER = 0
    BTG_CLIENT = 1

    def __init__(self,
                 back_plane_ip_address=None,
                 subscriber_port='43125',
                 publisher_port='43124',
                 process_name=None,
                 loop_time=.001,
                 gateway_type=BTG_SERVER,
                 publish_topic=None,
                 uuid='e35d6386-1802-414f-b2b9-375c92fa23e0',
                 server_bt_address=None,
                 subscriber_list=None,
                 json_data=False):
        """
        This method initialize the class for operation

        """
        # save input parameters as instance variables
        self.back_plane_ip_address = back_plane_ip_address
        self.subscriber_port = subscriber_port
        self.publisher_port = publisher_port
        self.loop_time = loop_time
        self.gateway_type = gateway_type

        # set the name for the banner depending upon client or server
        if process_name is None:
            if self.gateway_type == self.BTG_CLIENT:
                self.process_name = 'BanyanBluetoothClient'
            else:
                self.process_name = 'BanyanBluetoothServer'
        else:
            self.process_name = process_name

        self.publish_topic = publish_topic

        self.uuid = uuid
        self.server_bt_address = server_bt_address
        self.json_data = json_data

        # initialize the parent

        super(BlueToothGateway,
              self).__init__(back_plane_ip_address=self.back_plane_ip_address,
                             subscriber_port=self.subscriber_port,
                             publisher_port=self.publisher_port,
                             process_name=self.process_name,
                             loop_time=self.loop_time)

        self.subscriber_list = subscriber_list

        for topic in self.subscriber_list:
            self.set_subscriber_topic(topic)
            print('Subscribed to: ', topic)

        print('Publish to   : ', self.publish_topic)

        mac = self.find_local_mac_address()
        if mac:
            print('Local Bluetooth MAC Address: ', mac)
        else:
            print('No Bluetooth Interface Found - Exiting')
            sys.exit(0)

        if self.gateway_type == self.BTG_SERVER:
            self.server_sock = BluetoothSocket(RFCOMM)
            self.server_sock.bind(("", PORT_ANY))
            self.server_sock.listen(1)

            port = self.server_sock.getsockname()[1]

            advertise_service(
                self.server_sock,
                "BanyanBlueToothServer",
                service_id=uuid,
                service_classes=[uuid, SERIAL_PORT_CLASS],
                profiles=[SERIAL_PORT_PROFILE],
            )

            print("Waiting for connection on RFCOMM channel %d" % port)
            try:
                self.client_sock, self.client_info = self.server_sock.accept()
            except KeyboardInterrupt:
                self.clean_up()
                sys.exit(0)

            print("Accepted connection from ", self.client_info)
        else:
            service_matches = find_service(uuid=self.uuid,
                                           address=self.server_bt_address)

            if len(service_matches) == 0:
                print("Could not find the remote Bluetooth server - exiting")
                self.clean_up()
                sys.exit(0)

            first_match = service_matches[0]
            port = first_match["port"]
            name = first_match["name"]
            host = first_match["host"]

            print("connecting to \"%s\" on %s" % (name, host))

            # Create the client socket
            self.client_sock = BluetoothSocket(RFCOMM)
            self.client_sock.connect((host, port))

        # wrap the socket for both client and server
        self.bsock = BufferedSocket(self.client_sock)

        # create a thread to handle receipt of bluetooth data
        threading.Thread.__init__(self)
        self.daemon = True

        # start the thread
        self.start()

        # this will keep the program running forever
        try:
            self.receive_loop()
        except KeyboardInterrupt:
            self.clean_up()
            sys.exit(0)

    def incoming_message_processing(self, topic, payload):
        """
        Process the incoming Banyan message to
        be sent to the Bluetooth network
        :param topic: topic string
        :param payload: payload data
        """

        # if the bluetooth device requires json encoding
        if self.json_data:
            data_out = json.dumps(payload)
            data_out = data_out.encode('utf-8')

            try:
                self.bsock.send(data_out)
            except Exception as e:
                self.clean_up()
                raise RuntimeError('Write Error')
        else:
            # convert the payload to a string
            data_out = str(payload['report'])
            data_out = data_out.encode('utf-8')
            self.client_sock.send(data_out)

    def find_local_mac_address(self):
        """
        Get the local bluetooth mac address
        :return: mac address string or None
        """
        proc = subprocess.Popen(['hcitool', 'dev'],
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE)

        data = proc.communicate()

        data = data[0].decode()

        data = data.split('\t')
        if len(data) < 2:
            return None
        else:
            return data[2].strip()

    def run(self):
        """
        This is thread that receives packets from the bluetooth interface
        :return:
        """

        while True:
            # if json encoding look for termination character
            # used for a dictionary
            if self.json_data:
                try:
                    data = self.bsock.recv_until(b'}',
                                                 timeout=0,
                                                 with_delimiter=True)
                except KeyboardInterrupt:
                    self.clean_up()
                    sys.exit(0)
                except Exception as e:
                    continue

                data = data.decode()
                data = json.loads(data)

                self.publish_payload(data, self.publish_topic)

            # data is not json encoded
            else:
                try:
                    data = (self.client_sock.recv(1)).decode()
                except KeyboardInterrupt:
                    self.clean_up()
                    sys.exit(0)
                payload = {'command': data}
                self.publish_payload(payload, self.publish_topic)