示例#1
0
class CameraConnection():
    port = 10000 # class variable

    client = None # instance variables
    target = None
    adapter = None
    state = None
    index = 0
    waiting_for_stop = False
    server_socket = None
    size = None

    def __init__(self, target, adapter, size=None):
    	self.client = BluetoothAsyncSocket()
    	self.adapter = adapter
	self.client.bind( (self.adapter.bt_address, 0) )
	self.target = target
	self.target_t = (target, 1)
	self.size = size if size else 'QQVGA'
	self.streamserver = StreamServer('0.0.0.0', CameraConnection.port)
	self.streamserver.create_server_socket()
	CameraConnection.port+=1

    def connected(self):
	logger.info("got connected")
	self.state = FSM.WELCOME
	self.client.setReadReady(self.data_available)
	if len(self.client.read_buffer) > 0:
	    self.do_welcome()

    def connection_failed(self, condition):
    	self.client.setCallback(None)
	self.client.setErrCallback(None)
	self.client.setReadReady(None)
	self.adapter.disconnected(self.target)

    def disconnect(self):
	self.client.setCallback(None)
	self.client.setErrCallback(None)
	self.client.setReadReady(None)
	self.adapter.disconnected(self.target)
	self.client.close()

    def connect(self):
	self.state  = FSM.CONNECTING
	logger.info("connecting to %s from %s" % (self.target_t, 
					self.adapter.bt_address))

	if self.adapter.manager.zm_backend:
	    self.pipe = '/tmp/camera_%s.pipe' % (self.target)

	    if not os.path.exists(self.pipe):
		os.mkfifo(self.pipe)

	return self.client.connect_ex( 
		self.target_t, 
		self.connected,  
		self.connection_failed)

    def do_welcome(self):
	if 'ACK0000' not in self.client.read_buffer:
	    return

	logger.info("got welcome")
	self.client.read_buffer = ""

	self.state = FSM.SETUP
	protocol.set_command_mode(self.client)
	protocol.set_capture_mode(self.client, size=self.size)
	self.state = FSM.IDLE
	gobject.timeout_add(200,self.take_picture)

    def take_picture(self):
	logger.info("taking picture")
	self.state = FSM.STREAM
	protocol.send_command(self.client, "SET_PREVIEW_MODE")
	#gobject.timeout_add(300,self.ask_size)
	return False

    def ask_size(self):
	if self.state != FSM.ASK_SIZE:
	    return
	logger.info("asking size")
	self.state = FSM.GET_SIZE
	protocol.send_command(self.client, 'GET_CAPTURE_SIZE')

    def get_size(self):
	if not CAPTURE_SIZE.match(self.client.read_buffer):
	    return

	size = CAPTURE_SIZE.match(self.client.read_buffer).groupdict()['size']
	self.size = size
	logger.info("got size %s" % size)
	self.state = FSM.STREAM
	protocol.send_command(self.client, 'START_CAPTURE_SEND')

    def extract_picture(self, start, end):
	logger.info("got picture")

	self.streamserver.send_to_all(
	    self.client.read_buffer[start:end+2],
	    mimetype='image/jpeg'
	)

	if self.adapter.manager.zm_backend:
	    logger.info("writing %i bytes" % (end-start))
	    asyncpipe.write(self.pipe, self.client.read_buffer[start:end+2])

	if self.adapter.manager.op_backend:
	    self.adapter.manager.tellListener(
		signals.HANDLE_PICTURE,
		dongle = self.adapter.bt_address,
	        target = self.target,
		picture = self.client.read_buffer[start:end+2]
	    )
	self.index+=1
        self.client.read_buffer = self.client.read_buffer[end+2:]

    def wait_for_prompt(self):
	logger.info("wait for prompt")
	if time.time() - self.last > 2:
	    logger.info("2 seconds without data, disconnect")
	    self.disconnect()
	    return False
	return True

    def do_stream(self):
	start, end = protocol.find_jpeg(self.client.read_buffer)

	if start > -1 and end > -1:
	    self.extract_picture(start, end)
	    if self.index == -100:
		protocol.send_command(self.client, 'SET_COMMAND_MODE')
		self.state = FSM.IDLE
		self.last = time.time()
		gobject.timeout_add(100, self.wait_for_prompt)

    def data_available(self, amount):
	if self.state == FSM.WELCOME:
	    self.do_welcome()
	elif self.state == FSM.SETUP:
	    self.do_setup()
	elif self.state == FSM.IDLE:
	    logger.info("ignoring I'm in idle")
	    self.last = time.time()
	    self.client.read_buffer = ""
	elif self.state == FSM.ASK_SIZE:
	    self.ask_size()
	elif self.state == FSM.GET_SIZE:
	    self.get_size()
	elif self.state == FSM.STREAM:
	    self.do_stream()
	else:
	    logger.debug("not valid state %s" % self.state)
class CameraConnection():
    port = 10000  # class variable

    client = None  # instance variables
    target = None
    adapter = None
    state = None
    index = 0
    waiting_for_stop = False
    server_socket = None
    size = None

    def __init__(self, target, adapter, size=None):
        self.client = BluetoothAsyncSocket()
        self.adapter = adapter
        self.client.bind((self.adapter.bt_address, 0))
        self.target = target
        self.target_t = (target, 1)
        self.size = size if size else 'QQVGA'
        self.streamserver = StreamServer('0.0.0.0', CameraConnection.port)
        self.streamserver.create_server_socket()
        CameraConnection.port += 1

    def connected(self):
        logger.info("got connected")
        self.state = FSM.WELCOME
        self.client.setReadReady(self.data_available)
        if len(self.client.read_buffer) > 0:
            self.do_welcome()

    def connection_failed(self, condition):
        self.client.setCallback(None)
        self.client.setErrCallback(None)
        self.client.setReadReady(None)
        self.adapter.disconnected(self.target)

    def disconnect(self):
        self.client.setCallback(None)
        self.client.setErrCallback(None)
        self.client.setReadReady(None)
        self.adapter.disconnected(self.target)
        self.client.close()

    def connect(self):
        self.state = FSM.CONNECTING
        logger.info("connecting to %s from %s" %
                    (self.target_t, self.adapter.bt_address))

        if self.adapter.manager.zm_backend:
            self.pipe = '/tmp/camera_%s.pipe' % (self.target)

            if not os.path.exists(self.pipe):
                os.mkfifo(self.pipe)

        return self.client.connect_ex(self.target_t, self.connected,
                                      self.connection_failed)

    def do_welcome(self):
        if 'ACK0000' not in self.client.read_buffer:
            return

        logger.info("got welcome")
        self.client.read_buffer = ""

        self.state = FSM.SETUP
        protocol.set_command_mode(self.client)
        protocol.set_capture_mode(self.client, size=self.size)
        self.state = FSM.IDLE
        gobject.timeout_add(200, self.take_picture)

    def take_picture(self):
        logger.info("taking picture")
        self.state = FSM.STREAM
        protocol.send_command(self.client, "SET_PREVIEW_MODE")
        #gobject.timeout_add(300,self.ask_size)
        return False

    def ask_size(self):
        if self.state != FSM.ASK_SIZE:
            return
        logger.info("asking size")
        self.state = FSM.GET_SIZE
        protocol.send_command(self.client, 'GET_CAPTURE_SIZE')

    def get_size(self):
        if not CAPTURE_SIZE.match(self.client.read_buffer):
            return

        size = CAPTURE_SIZE.match(self.client.read_buffer).groupdict()['size']
        self.size = size
        logger.info("got size %s" % size)
        self.state = FSM.STREAM
        protocol.send_command(self.client, 'START_CAPTURE_SEND')

    def extract_picture(self, start, end):
        logger.info("got picture")

        self.streamserver.send_to_all(self.client.read_buffer[start:end + 2],
                                      mimetype='image/jpeg')

        if self.adapter.manager.zm_backend:
            logger.info("writing %i bytes" % (end - start))
            asyncpipe.write(self.pipe, self.client.read_buffer[start:end + 2])

        if self.adapter.manager.op_backend:
            self.adapter.manager.tellListener(
                signals.HANDLE_PICTURE,
                dongle=self.adapter.bt_address,
                target=self.target,
                picture=self.client.read_buffer[start:end + 2])
        self.index += 1
        self.client.read_buffer = self.client.read_buffer[end + 2:]

    def wait_for_prompt(self):
        logger.info("wait for prompt")
        if time.time() - self.last > 2:
            logger.info("2 seconds without data, disconnect")
            self.disconnect()
            return False
        return True

    def do_stream(self):
        start, end = protocol.find_jpeg(self.client.read_buffer)

        if start > -1 and end > -1:
            self.extract_picture(start, end)
            if self.index == -100:
                protocol.send_command(self.client, 'SET_COMMAND_MODE')
                self.state = FSM.IDLE
                self.last = time.time()
                gobject.timeout_add(100, self.wait_for_prompt)

    def data_available(self, amount):
        if self.state == FSM.WELCOME:
            self.do_welcome()
        elif self.state == FSM.SETUP:
            self.do_setup()
        elif self.state == FSM.IDLE:
            logger.info("ignoring I'm in idle")
            self.last = time.time()
            self.client.read_buffer = ""
        elif self.state == FSM.ASK_SIZE:
            self.ask_size()
        elif self.state == FSM.GET_SIZE:
            self.get_size()
        elif self.state == FSM.STREAM:
            self.do_stream()
        else:
            logger.debug("not valid state %s" % self.state)
class Client(object):
	def __init__(self, callback=None, err_callback=None, loop=None):
	
		self.max_packet_length = 0xffff
		self.obex_version = OBEX_Version()
		self.__callback=callback
		self.__err_callback=err_callback
		self.loop = loop

		# internal state variables
		self.state = common.IDLE
		self.state_put = common.PUT_IDLE
		
		# internal holders
		self.pending_headers = []
		self.response_handler = responses.ResponseHandler()
		self.length = 0
		self.type = None
		self.invalid = False
		
		# a state flag that allow us to know if we have to send more
		# headers as soon as we get a reply		
		self.sending_headers = False
		
	def cleanup(self):
	    self.socket.remove_callbacks()
	    self.socket.close()
	
	def callback(self, *args, **kwargs):
		if self.invalid:
			return
		print "callback", args, kwargs
		if callable(self.__callback):
			self.__callback(self, *args, **kwargs)
	
	def err_callback(self, *args, **kwargs):
		print "err_callback", args, kwargs
		self.invalid = True
		if callable(self.__err_callback):
			self.__err_callback(self, *args, **kwargs)
			
	def internal_callback(self, *args, **kwargs):
		if self.state != common.PUT:
			return self.callback(*args, **kwargs)
			
		if self.state_put == common.PUT_HEADER:
			return self.put_headers_done(*args, **kwargs)
		
		if self.state_put == common.PUT_BODY:
			return self.put_body_done(*args, **kwargs)
			
		if self.state_put == common.PUT_FINAL:
			return self.put_done(*args, **kwargs)
			
		raise Exception("Invalid state %s %s" % (
												common.STATES[self.state],
												common.STATES_PUT[self.state_put]
						))
	
	def data_ready(self, amount):
		print "data_ready", amount
		if self.length == 0:
			if amount < 3:
				return
		
			format = ">BH"
			data = self.socket.recv(3)
			amount=amount-3
			type, length = struct.unpack(format, data)
		else:
			type = self.type
			length = self.length
		
		if length-3>amount:
			self.type = type
			self.length = length
			self.data = data
			print "pending data", length
			return
		data += self.socket.recv(length - 3)
		self.type = 0
		self.length = 0
		print type, length, len(data)
			
		if isinstance(self.request, requests.Connect):
			response = self.response_handler.decode_connection(type, length, data)
			self.remote_info = response
		else:
			response = self.response_handler.decode(type, length, data)
		
		if self.sending_headers and not isinstance(response, responses.Continue):
			self.err_callback(error=common.ObexError(response))
			return

		self.internal_callback(response=response)

	def __connected_rfcomm(self, *args, **kwargs):
		self.callback(*args[1:], **kwargs)
	
	def __failed_rfcomm(self, *args, **kwargs):
		self.err_callback(error=common.ErrnoError(args[0]), *args[1:], **kwargs)	

	def connect_rfcomm(self, address, port, callback, err_callback, bind=None):
		'''
			Start up the RFcomm level connection. Once this successed
			you have to call connect_rfcomm
		'''
		print "connecting rfcomm"
		self.socket = BluetoothAsyncSocket()
		self.__callback = callback
		self.__err_callback = err_callback
		if bind:
		    self.socket._sock.bind((bind, 0))
		self.socket.connect_ex((address, port), 
							callback=self.__connected_rfcomm, 
							err_callback=self.__failed_rfcomm)
		self.state = common.CONNECTING_RFCOMM
		return common.ReplyPending()
	
	def connect_obex(self, header_list=[]):
		'''
			Start the Obex connection.
		'''
		flags = 0
		data = (self.obex_version.to_byte(), flags, self.max_packet_length)

		max_length = self.max_packet_length
		request = requests.Connect(data)

		# upgrade our state
		self.state = common.CONNECTING_OBEX
		
		# register to get informed when more data is available
		self.socket.setReadReady(self.data_ready) 

		self.pending_headers = list(header_list)
		self._send_headers(request, max_length)

	def _send_headers(self, request, max_length):
	
		"""Convenience method to add headers to a request and send one or
		more requests with those headers."""
		
		while self.pending_headers:
		
			if request.add_header(self.pending_headers[0], max_length):
				self.pending_headers.pop(0)
			else:
				print "sending on headers", request.encode()
				self.socket.sendall(request.encode())
				request.reset_headers()
				self.sending_headers = True
				self.request = request
				# now we wait for data
				return common.ReplyPending
		
		self.sending_headers = False
		# Always send at least one request.
		if isinstance(request, requests.Get):
			# Turn the last Get request containing the headers into a
			# Get_Final request.
			request.code = requests.Get_Final.code
		
		print "sending", len(request.encode())
		self.socket.sendall(request.encode())
		self.request = request
		return common.ReplyPending
	
	def put_headers_done(self, response):
		if not isinstance(response, responses.Continue):
			return self.err_callback(common.ObexError(response))
		self.put_body()
		
	def put_body_done(self, response):
		if not isinstance(response, responses.Continue):
			return self.err_callback(common.ObexError(response))
		
		self.put_body()
		
	def put_done(self, response):
		if not isinstance(response, responses.Success):
			return self.err_callback(common.ObexError(response))
		
		self.callback(response)
		self.state = common.CONNECTED
		self.state_put = common.PUT_IDLE
		
		
	def put_body(self):
		max_length = self.remote_info.max_packet_length
		file_data = self.file_data
		
		# Send the file data.
		
		# The optimum size is the maximum packet length accepted by the
		# remote device minus three bytes for the header ID and length
		# minus three bytes for the request.
		optimum_size = max_length - 3 - 3
		
		data = file_data[:optimum_size]
		self.file_data=self.file_data[optimum_size:]
		
		if len(data) == 0:
			raise Exception("work done")
		
		if len(self.file_data) > 0:
			self.state_put = common.PUT_BODY
			request = requests.Put()
			request.add_header(headers.Body(data, False), max_length)
			self.socket.sendall(request.encode())			
		else:
			self.state_put = common.PUT_FINAL
			request = requests.Put_Final()
			request.add_header(headers.End_Of_Body(data, False), max_length)
			self.socket.sendall(request.encode())
	
	def put(self, name, file_data, header_list = ()):
		"""put(self, name, file_data, header_list = ())
		
		Sends a file with the given name, containing the file_data specified,
		to the server for storage in the current directory for the session,
		and returns the response.
		
		Additional headers can be sent by passing a sequence as the
		header_list keyword argument. These will be sent after the name and
		file length information associated with the name and file_data
		supplied.
		"""
		
		header_list = [
					headers.Name(name),
					headers.Length(len(file_data))
			] + list(header_list)
		
		max_length = self.remote_info.max_packet_length
		request = requests.Put()
		self.state = common.PUT
		self.state_put = common.PUT_HEADER
		
		self.file_data = file_data
		self.pending_headers = header_list
		
		self._send_headers(request, max_length)