Ejemplo n.º 1
0
 def connect(self, address):
     # Set up the socket handling
     self.__send_q = Queue()
     self.recv_q = Queue()
     self.socket = SocketHandler(address,
                                 self.__send_q,
                                 self.recv_q,
                                 debug=self.debug,
                                 sentinel=_sentinel)
     self.socket.start()
     # get the version once connected
     self.version = self.__send('version')
Ejemplo n.º 2
0
 def connect(self, address):
   # Set up the socket handling
   self.__send_q = Queue()
   self.recv_q = Queue()
   self.socket = SocketHandler(address, self.__send_q, self.recv_q, debug=self.debug, sentinel = _sentinel)
   self.socket.start()
   # get the version once connected
   self.version   = self.__send('version')
Ejemplo n.º 3
0
class Mirobot:
  def __init__(self, address, debug = False):
    self.__send_q = Queue()
    self.recv_q = Queue()
    self.socket = SocketHandler(address, self.__send_q, self.recv_q, debug=debug, sentinel = _sentinel)
    self.socket.start()

  def forward(self, distance):
    self.__send({'cmd':'forward', 'arg':str(distance)}, distance/20)

  def back(self, distance):
    self.__send({'cmd':'back', 'arg':str(distance)}, distance/20)

  def left(self, degrees):
    self.__send({'cmd':'left', 'arg':str(degrees)}, degrees/20)

  def right(self, degrees):
    self.__send({'cmd':'right', 'arg':str(degrees)}, degrees/20)

  def penup(self):
    self.__send({'cmd':'penup'}, 1)

  def pendown(self):
    self.__send({'cmd':'pendown'}, 1)

  def beep(self, milliseconds):
    self.__send({'cmd':'beep', 'arg':str(milliseconds)}, milliseconds / 500)
  
  def disconnect(self):
    self.__send_q.put(_sentinel)
  
  def __send(self, msg, timeout):
    msg['id'] = self.generate_id()
    self.__send_q.put(msg)
    timeout += time.time()
    while True:
      if self.recv_q.qsize() > 0:
        incoming = self.recv_q.get()
        if incoming['status'] == 'complete' and incoming['id'] == msg['id']:
          return
      if time.time() >= timeout:
        raise IOError("Mirobot timed out")
      time.sleep(0.05)

  def generate_id(self):
    return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(8))
Ejemplo n.º 4
0
class Mirobot:
    def __init__(self, address=None, debug=False):
        # Initialisation for the id field
        self.nonce = ''.join(
            random.choice(string.ascii_letters + string.digits)
            for _ in range(4))
        self.n = 0
        self.debug = debug

        # callbacks
        self.__on_error = None
        self.__on_collide = None
        self.__on_follow = None

        if address:
            self.connect(address)

    def connect(self, address):
        # Set up the socket handling
        self.__send_q = Queue()
        self.recv_q = Queue()
        self.socket = SocketHandler(address,
                                    self.__send_q,
                                    self.recv_q,
                                    debug=self.debug,
                                    sentinel=_sentinel)
        self.socket.start()
        # get the version once connected
        self.version = self.__send('version')

    def connectMenu(self, devices):
        print("Select the Mirobot to connect to:")
        for i, device in enumerate(devices):
            print("  %i: %s" % (i + 1, device['name']))
        try:
            choice = raw_input("Select a number:")
        except:
            choice = input("Select a number: ")
        return choice

    def autoConnect(self, id=None, interactive=False):
        try:
            res = request.urlopen(
                "http://local.mirobot.io/devices.json").read()
        except:
            raise Exception("Could not connect to discovery server")

        try:
            devices = json.loads(str(res, 'utf-8'))
        except TypeError:
            devices = json.loads(res)

        print(devices)
        if interactive:
            choice = self.connectMenu(devices['devices'])
            print("Connecting to: %s" %
                  devices['devices'][int(choice) - 1]['name'])
            self.connect(devices['devices'][int(choice) - 1]['address'])
        else:
            if id:
                filtered = [
                    item for item in devices['devices'] if item['name'] == id
                ]
                if len(filtered) == 0:
                    raise Exception("No Mirobots found with id: %s" % id)
                elif len(filtered) == 1:
                    # Connect to the only device we've found
                    self.connect(filtered[0]['address'])
                else:
                    raise Exception("Multiple Mirobots found with id: %s" % id)
            else:
                if len(devices['devices']) == 0:
                    raise Exception("No Mirobots found")
                elif len(devices['devices']) == 1:
                    # Connect to the only device we've found
                    self.connect(devices['devices'][0]['address'])
                else:
                    raise Exception(
                        "Too many Mirobots found to auto connect without specifying an ID"
                    )

    def errorNotify(self, on_error):
        self.__on_error = on_error

    def collideNotify(self, on_collide):
        enabled = bool(on_collide)
        self.__on_collide = on_collide
        self.__send('collideNotify', ('false', 'true')[enabled])

    def followNotify(self, on_follow):
        enabled = bool(on_follow)
        self.__on_follow = on_follow
        self.__send('followNotify', ('false', 'true')[enabled])

    def ping(self):
        return self.__send('ping')

    def uptime(self):
        return self.__send('uptime')

    def forward(self, distance):
        return self.__send('forward', distance, distance / 20)

    def back(self, distance):
        return self.__send('back', distance, distance / 20)

    def left(self, degrees):
        return self.__send('left', degrees, degrees / 20)

    def right(self, degrees):
        return self.__send('right', degrees, degrees / 20)

    def penup(self):
        return self.__send('penup')

    def pendown(self):
        return self.__send('pendown')

    def beep(self, milliseconds=500):
        return self.__send('beep', milliseconds, milliseconds / 500)

    def collideState(self):
        return self.__send('collideState')

    def followState(self):
        return self.__send('followState')

    def disconnect(self):
        self.__send_q.put(_sentinel)

    def __send(self, cmd, arg=None, timeout=1):
        # Assemble the message
        msg = {'cmd': cmd}
        if (arg is not None):
            msg['arg'] = str(arg)

        # Send the message and handle exceptions
        try:
            return self.__send_or_raise(msg, timeout)
        except Exception as x:
            if not self.__on_error:
                raise
            return self.__on_error(x, msg, timeout, self)

    def __send_or_raise(self, msg, timeout):
        msg_id = msg['id'] = self.generate_id()
        self.__send_q.put(msg)
        deadline = timeout + time.time()
        accepted = False
        while True:
            try:
                timeout = max(1, deadline - time.time())
                incoming = self.recv_q.get(block=True, timeout=timeout)
            except KeyboardInterrupt as e:
                self.disconnect()
                raise e
            except:  # .get raises "Empty"
                if (accepted):
                    raise IOError(
                        "Mirobot timed out awaiting completion of %r" %
                        (msg, ))
                raise IOError("Mirobot timed out awaiting acceptance of %r" %
                              (msg, ))

            try:
                rx_id = incoming.get('id', '???')
                if rx_id != msg_id:
                    if (rx_id == 'collide'):
                        self.__collide(incoming)
                        continue
                    if (rx_id == 'follow'):
                        self.__follow(incoming)
                        continue
                    raise IOError(
                        "Received message ID (%s) does not match expected (%s)"
                        % (rx_id, msg_id))
                rx_status = incoming.get('status', '???')
                if rx_status == 'accepted':
                    accepted = True
                elif rx_status == 'complete':
                    return incoming.get('msg', None)
                elif rx_status == 'notify':
                    pass
                else:
                    raise IOError("Received message status (%s) unexpected" %
                                  (rx_status, ))
            finally:
                self.recv_q.task_done()

    def __collide(self, msg):
        if self.__on_collide:
            left = msg['msg'] in ('both', 'left')
            right = msg['msg'] in ('both', 'right')
            self.__on_collide(left, right, msg, self)

    def __follow(self, msg):
        if self.__on_follow:
            state = int(msg['msg'])
            self.__on_follow(state, msg, self)

    def generate_id(self):
        self.n = (self.n + 1) % 0x10000
        return '%s%04x' % (self.nonce, self.n)
Ejemplo n.º 5
0
class Mirobot:
  def __init__(self, address = None, debug = False):
    # Initialisation for the id field
    self.nonce  = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(4))
    self.n      = 0
    self.debug = debug

    # callbacks
    self.__on_error    = None
    self.__on_collide  = None
    self.__on_follow   = None

    if address:
      self.connect(address)

  def connect(self, address):
    # Set up the socket handling
    self.__send_q = Queue()
    self.recv_q = Queue()
    self.socket = SocketHandler(address, self.__send_q, self.recv_q, debug=self.debug, sentinel = _sentinel)
    self.socket.start()
    # get the version once connected
    self.version   = self.__send('version')

  def connectMenu(self, devices):
    print("Select the Mirobot to connect to:")
    for i, device in enumerate(devices):
      print("  %i: %s" % (i+1, device['name']))
    try:
      choice = raw_input("Select a number:")
    except:
      choice = input("Select a number: ")
    return choice

  def autoConnect(self, id = None, interactive = False):
    try:
      res = request.urlopen("http://local.mirobot.io/devices.json").read()
    except:
      raise Exception("Could not connect to discovery server")

    try:
      devices = json.loads(str(res, 'utf-8'))
    except TypeError:
      devices = json.loads(res)

    print(devices)
    if interactive:
      choice = self.connectMenu(devices['devices'])
      print("Connecting to: %s" % devices['devices'][int(choice)-1]['name'])
      self.connect(devices['devices'][int(choice)-1]['address'])
    else:
      if id:
        filtered = [item for item in devices['devices'] if item['name'] == id]
        if len(filtered) == 0:
          raise Exception("No Mirobots found with id: %s" % id)
        elif len(filtered) == 1:
          # Connect to the only device we've found
          self.connect(filtered[0]['address'])
        else:
          raise Exception("Multiple Mirobots found with id: %s" % id)
      else:
        if len(devices['devices']) == 0:
          raise Exception("No Mirobots found")
        elif len(devices['devices']) == 1:
          # Connect to the only device we've found
          self.connect(devices['devices'][0]['address'])
        else:
          raise Exception("Too many Mirobots found to auto connect without specifying an ID")

  def errorNotify(self, on_error):
    self.__on_error = on_error

  def collideNotify(self, on_collide):
    enabled = bool(on_collide)
    self.__on_collide = on_collide
    self.__send('collideNotify', ('false','true')[enabled])

  def followNotify(self, on_follow):
    enabled = bool(on_follow)
    self.__on_follow = on_follow
    self.__send('followNotify', ('false','true')[enabled])

  def ping(self):
    return self.__send('ping')

  def uptime(self):
    return self.__send('uptime')

  def forward(self, distance):
    return self.__send('forward', distance, distance/20)

  def back(self, distance):
    return self.__send('back',    distance, distance/20)

  def left(self, degrees):
    return self.__send('left',    degrees,  degrees/20)

  def right(self, degrees):
    return self.__send('right',   degrees,  degrees/20)

  def penup(self):
    return self.__send('penup')

  def pendown(self):
    return self.__send('pendown')

  def beep(self, milliseconds = 500):
    return self.__send('beep',    milliseconds, milliseconds / 500)

  def collideState(self):
    return self.__send('collideState')

  def followState(self):
    return self.__send('followState')

  def disconnect(self):
    self.__send_q.put(_sentinel)

  def __send(self, cmd, arg = None, timeout = 1):
    # Assemble the message
    msg = {'cmd': cmd}
    if (arg is not None):
      msg['arg'] = str(arg)

    # Send the message and handle exceptions
    try:
      return self.__send_or_raise(msg, timeout)
    except Exception as x:
      if not self.__on_error:
        raise
      return self.__on_error(x, msg, timeout, self)

  def __send_or_raise(self, msg, timeout):
    msg_id = msg['id'] = self.generate_id()
    self.__send_q.put(msg)
    deadline = timeout + time.time()
    accepted = False
    while True:
      try:
        timeout = max(1, deadline - time.time())
        incoming = self.recv_q.get(block = True, timeout = timeout)
      except KeyboardInterrupt as e:
        self.disconnect()
        raise e
      except: # .get raises "Empty"
        if (accepted):
          raise IOError("Mirobot timed out awaiting completion of %r" % (msg,))
        raise IOError("Mirobot timed out awaiting acceptance of %r" % (msg,))

      try:
        rx_id = incoming.get('id','???')
        if rx_id != msg_id:
          if (rx_id == 'collide'):
            self.__collide(incoming)
            continue
          if (rx_id == 'follow'):
            self.__follow(incoming)
            continue
          raise IOError("Received message ID (%s) does not match expected (%s)" % (rx_id, msg_id))
        rx_status = incoming.get('status','???')
        if rx_status == 'accepted':
          accepted = True
        elif rx_status == 'complete':
          return incoming.get('msg',None)
        elif rx_status == 'notify':
          pass
        else:
          raise IOError("Received message status (%s) unexpected" % (rx_status,))
      finally:
        self.recv_q.task_done()

  def __collide(self, msg):
    if self.__on_collide:
      left  = msg['msg'] in ('both','left')
      right = msg['msg'] in ('both','right')
      self.__on_collide(left, right, msg, self)

  def __follow(self, msg):
    if self.__on_follow:
      state  = int(msg['msg'])
      self.__on_follow(state, msg, self)

  def generate_id(self):
    self.n = (self.n + 1) % 0x10000
    return '%s%04x' % (self.nonce, self.n)
Ejemplo n.º 6
0
 def __init__(self, address, debug = False):
   self.__send_q = Queue()
   self.recv_q = Queue()
   self.socket = SocketHandler(address, self.__send_q, self.recv_q, debug=debug, sentinel = _sentinel)
   self.socket.start()