def _start_fired(self):
     """
 Handle start udp broadcast button. Registers callbacks on self.link for each of the self.msgs
 If self.msgs is None, it registers one generic callback for all messages
 """
     self.running = True
     try:
         self.func = UdpLogger(self.ip_ad, self.port)
         self.link.add_callback(self.func, self.msgs)
     except:
         import traceback
         print traceback.format_exc()
 def _start_fired(self):
   """
   Handle start udp broadcast button. Registers callbacks on self.link for each of the self.msgs
   If self.msgs is None, it registers one generic callback for all messages
   """
   self.running = True
   try:
     self.func = UdpLogger(self.ip_ad, self.port)
     self.link.add_callback(self.func, self.msgs)
   except:
     import traceback
     print traceback.format_exc()
Exemple #3
0
def main():
    args = get_args()
    address = args.address[0]
    udp_port = args.udp_port[0]

    with PySerialDriver(args.serial_port[0], args.baud[0]) as driver:
        with Handler(driver.read, driver.write) as handler:
            with UdpLogger(address, udp_port) as udp:
                handler.add_callback(udp)

                try:
                    while True:
                        time.sleep(0.1)
                except KeyboardInterrupt:
                    pass
Exemple #4
0
def main():
    """Simple command line interface for running the udp bridge to
    forward observation messages

    """
    args = get_args()
    port = int(args.udp_port[0])
    address = args.address[0]
    with PySerialDriver(args.serial_port[0], args.baud[0]) as driver:
        with Handler(Framer(driver.read, driver.write)) as handler:
            with UdpLogger(address, port) as udp:
                handler.add_callback(udp, OBS_MSGS)
                # Note, we may want to send the ephemeris message in the future
                # but the message is too big for MAVProxy right now
                try:
                    while True:
                        time.sleep(0.1)
                except KeyboardInterrupt:
                    pass
Exemple #5
0
class SbpRelayView(HasTraits):
    """
  UDP Relay view- Class allows user to specify port, IP address, and message set
  to relay over UDP
  """
    running = Bool(False)
    configured = Bool(False)
    broadcasting = Bool(False)
    msg_enum = Enum('Observations', 'All')
    ip_ad = String(DEFAULT_UDP_ADDRESS)
    port = Int(DEFAULT_UDP_PORT)
    information = String(
        'UDP Streaming\n\nBroadcast SBP information received by'
        ' the console to other machines or processes over UDP. With the \'Observations\''
        ' radio button selected, the console will broadcast the necessary information'
        ' for a rover Piksi to acheive an RTK solution.'
        '\n\nThis can be used to stream observations to a remote Piksi through'
        ' aircraft telemetry via ground control software such as MAVProxy or'
        ' Mission Planner.')
    http_information = String(
        'Skylark - Experimental Piksi Networking\n\n'
        "Skylark is Swift Navigation's Internet service for connecting Piksi receivers without the use of a radio. To receive GPS observations from the closest nearby Piksi base station (within 5km), click Connect to Skylark.\n\n"
    )
    start = Button(label='Start', toggle=True, width=32)
    stop = Button(label='Stop', toggle=True, width=32)
    connected_rover = Bool(False)
    connect_rover = Button(label='Connect to Skylark', toggle=True, width=32)
    disconnect_rover = Button(label='Disconnect from Skylark',
                              toggle=True,
                              width=32)
    base_pragma = String()
    rover_pragma = String()
    base_device_uid = String()
    rover_device_uid = String()
    toggle = True
    view = View(
        VGroup(
            spring,
            HGroup(
                VGroup(
                    Item('running',
                         show_label=True,
                         style='readonly',
                         visible_when='running'),
                    Item('msg_enum',
                         label="Messages to broadcast",
                         style='custom',
                         enabled_when='not running'),
                    Item('ip_ad',
                         label='IP Address',
                         enabled_when='not running'),
                    Item('port', label="Port", enabled_when='not running'),
                    HGroup(
                        spring,
                        UItem('start',
                              enabled_when='not running',
                              show_label=False),
                        UItem('stop', enabled_when='running',
                              show_label=False), spring)),
                VGroup(
                    Item('information',
                         label="Notes",
                         height=10,
                         editor=MultilineTextEditor(
                             TextEditor(multi_line=True)),
                         style='readonly',
                         show_label=False,
                         resizable=True,
                         padding=15),
                    spring,
                ),
            ), spring,
            HGroup(
                VGroup(
                    HGroup(
                        spring,
                        UItem('connect_rover',
                              enabled_when='not connected_rover',
                              show_label=False),
                        UItem('disconnect_rover',
                              enabled_when='connected_rover',
                              show_label=False), spring),
                    HGroup(spring, Item('base_pragma', label='Base option '),
                           Item('base_device_uid', label='Base device '),
                           spring),
                    HGroup(spring, Item('rover_pragma', label='Rover option'),
                           Item('rover_device_uid', label='Rover device'),
                           spring),
                ),
                VGroup(
                    Item('http_information',
                         label="Notes",
                         height=10,
                         editor=MultilineTextEditor(
                             TextEditor(multi_line=True)),
                         style='readonly',
                         show_label=False,
                         resizable=True,
                         padding=15),
                    spring,
                ),
            ), spring))

    def __init__(self,
                 link,
                 device_uid=None,
                 base=DEFAULT_BASE,
                 whitelist=None):
        """
    Traits tab with UI for UDP broadcast of SBP.

    Parameters
    ----------
    link : sbp.client.handler.Handler
      Link for SBP transfer to/from Piksi.
    device_uid : str
      Piksi Device UUID (defaults to None)
    base : str
      HTTP endpoint
    whitelist : [int] | None
      Piksi Device UUID (defaults to None)

    """
        self.link = link
        self.http = HTTPDriver(None, base)
        self.net_link = None
        self.fwd = None
        self.func = None
        # Whitelist used for UDP broadcast view
        self.msgs = OBS_MSGS
        # register a callback when the msg_enum trait changes
        self.on_trait_change(self.update_msgs, 'msg_enum')
        # Whitelist used for Skylark broadcasting
        self.whitelist = whitelist
        self.device_uid = None
        self.python_console_cmds = {'update': self}

    def update_msgs(self):
        """Updates the instance variable msgs which store the msgs that we
    will send over UDP.

    """
        if self.msg_enum == 'Observations':
            self.msgs = OBS_MSGS
        elif self.msg_enum == 'All':
            self.msgs = [None]
        else:
            raise NotImplementedError

    def set_route(self, serial_id, channel=CHANNEL_UUID):
        """Sets serial_id hash for HTTP headers.

    Parameters
    ----------
    serial_id : int
      Piksi device ID
    channel : str
      UUID namespace for device UUID

    """
        device_uid = str(get_uuid(channel, serial_id))
        self.device_uid = device_uid
        if self.http:
            self.http.device_uid = device_uid

    def _prompt_networking_error(self, text):
        """Nonblocking prompt for a networking error.

    Parameters
    ----------
    text : str
      Helpful error message for the user

    """
        prompt = CallbackPrompt(title="Networking Error",
                                actions=[close_button])
        prompt.text = text
        prompt.run(block=False)

    def _prompt_setting_error(self, text):
        """Nonblocking prompt for a device setting error.

    Parameters
    ----------
    text : str
      Helpful error message for the user

    """
        prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
        prompt.text = text
        prompt.run(block=False)

    def _retry_read(self):
        """Retry read connections. Intended to be called by
    _connect_rover_fired.

    """
        i = 0
        repeats = 5
        _rover_pragma = self.rover_pragma
        _rover_device_uid = self.rover_device_uid or self.device_uid
        while self.http and not self.http.connect_read(
                device_uid=_rover_device_uid, pragma=_rover_pragma):
            print "Attempting to read observation from Skylark..."
            time.sleep(0.1)
            i += 1
            if i >= repeats:
                msg = (
                    "\nUnable to receive observations from Skylark!\n\n"
                    "Please check that:\n"
                    " - you have a network connection\n"
                    " - your Piksi has a single-point position\n"
                    " - a Skylark-connected Piksi receiver \n   is nearby (within 5km)"
                )
                self._prompt_networking_error(msg)
                self.http.read_close()
                return
        print "Connected as a rover!"
        with Handler(Framer(self.http.read, self.http.write)) as net_link:
            self.net_link = net_link
            self.fwd = Forwarder(net_link, swriter(self.link))
            self.fwd.start()
            while True:
                time.sleep(1)
                if not net_link.is_alive():
                    sys.stderr.write(
                        "Network observation stream disconnected!")
                    break
        # Unless the user has initiated a reconnection, assume here that the rover
        # still wants to be connected, so if we break out of the handler loop,
        # cleanup rover connection and try reconnecting.
        if self.connected_rover:
            sys.stderr.write("Going for a networking reconnection!")
            self._disconnect_rover_fired()
            self._connect_rover_fired()

    def _connect_rover_fired(self):
        """Handle callback for HTTP rover connections.

    """
        if not self.device_uid:
            msg = "\nDevice ID not found!\n\nConnection requires a valid Piksi device ID."
            self._prompt_setting_error(msg)
            return
        if not self.http:
            self._prompt_networking_error("\nNetworking disabled!")
            return
        try:
            _base_pragma = self.base_pragma
            _base_device_uid = self.base_device_uid or self.device_uid
            if not self.http.connect_write(self.link,
                                           self.whitelist,
                                           device_uid=_base_device_uid,
                                           pragma=_base_pragma):
                msg = ("\nUnable to connect to Skylark!\n\n"
                       "Please check that you have a network connection.")
                self._prompt_networking_error(msg)
                self.http.close()
                self.connected_rover = False
                return
            self.connected_rover = True
            print "Connected as a base station!"
            executor = ThreadPoolExecutor(max_workers=2)
            executor.submit(self._retry_read)
        except:
            self.connected_rover = False
            import traceback
            print traceback.format_exc()

    def _disconnect_rover_fired(self):
        """Handle callback for HTTP rover disconnects.

    """
        if not self.device_uid:
            msg = "\nDevice ID not found!\n\nConnection requires a valid Piksi device ID."
            self._prompt_setting_error(msg)
            return
        if not self.http:
            self._prompt_networking_error("\nNetworking disabled!")
            return
        try:
            if self.connected_rover:
                self.http.close()
                self.connected_rover = False
                if self.fwd and self.net_link:
                    self.net_link.stop()
        except:
            self.connected_rover = False
            import traceback
            print traceback.format_exc()

    def _start_fired(self):
        """Handle start udp broadcast button. Registers callbacks on
    self.link for each of the self.msgs If self.msgs is None, it
    registers one generic callback for all messages.

    """
        self.running = True
        try:
            self.func = UdpLogger(self.ip_ad, self.port)
            self.link.add_callback(self.func, self.msgs)
        except:
            import traceback
            print traceback.format_exc()

    def _stop_fired(self):
        """Handle the stop udp broadcast button. It uses the self.funcs and
    self.msgs to remove the callbacks that were registered when the
    start button was pressed.

    """
        try:
            self.link.remove_callback(self.func, self.msgs)
            self.func.__exit__()
            self.func = None
            self.running = False
        except:
            import traceback
            print traceback.format_exc()
class SbpRelayView(HasTraits):
    """
  UDP Relay view- Class allows user to specify port, IP address, and message set
  to relay over UDP
  """
    running = Bool(False)
    configured = Bool(False)
    broadcasting = Bool(False)
    msg_enum = Enum('Observations', 'All')
    ip_ad = String(DEFAULT_UDP_ADDRESS)
    port = Int(DEFAULT_UDP_PORT)
    information = String(
        'This tab is used to broadcast SBP information received by'
        ' the console to other machines or processes over UDP. With the \'Observations\''
        ' radio button selected, the console will broadcast the necessary information'
        ' for a rover Piksi to acheive an RTK solution.'
        '\n\nThis tab can be used to stream observations to a remote Piksi through'
        ' aircraft telemetry via ground control software such as MAVProxy or'
        ' Mission Planner.')

    start = Button(label='Start', toggle=True, width=32)

    stop = Button(label='Stop', toggle=True, width=32)
    view = View(
        HGroup(
            VGroup(
                Item('running',
                     show_label=True,
                     style='readonly',
                     visible_when='running'),
                Item('msg_enum',
                     label="Messages to broadcast",
                     style='custom',
                     enabled_when='not running'),
                Item('ip_ad', label='IP Address', enabled_when='not running'),
                Item('port', label="Port", enabled_when='not running'),
                HGroup(
                    spring,
                    UItem('start',
                          enabled_when='not running',
                          show_label=False),
                    UItem('stop', enabled_when='running', show_label=False),
                    spring)),
            VGroup(
                Item('information',
                     label="Notes",
                     height=10,
                     editor=MyTextEditor(TextEditor(multi_line=True)),
                     style='readonly',
                     show_label=False,
                     resizable=True,
                     padding=15),
                spring,
            ),
        ))

    def __init__(self, link):
        """
    Traits tab with UI for UDP broadcast of SBP.

    Parameters
    ----------
    link : sbp.client.handler.Handler
      Link for SBP transfer to/from Piksi.
    """
        self.func = None
        self.msgs = OBS_MSGS
        # register a callback when the msg_enum trait changes
        self.on_trait_change(self.update_msgs, 'msg_enum')
        self.link = link
        self.python_console_cmds = {'update': self}

    def update_msgs(self):
        """
    Updates the instance variable msgs which store the msgs that we will send over UDP
    """
        if self.msg_enum == 'Observations':
            self.msgs = OBS_MSGS
        elif self.msg_enum == 'All':
            self.msgs = [None]
        else:
            raise NotImplementedError

    def _start_fired(self):
        """
    Handle start udp broadcast button. Registers callbacks on self.link for each of the self.msgs
    If self.msgs is None, it registers one generic callback for all messages
    """
        self.running = True
        try:
            self.func = UdpLogger(self.ip_ad, self.port)
            self.link.add_callback(self.func, self.msgs)
        except:
            import traceback
            print traceback.format_exc()

    def _stop_fired(self):
        """
    Handle the stop udp broadcast button. It uses the self.funcs and self.msgs to remove
    the callbacks that were registered when the start button was pressed.
    """
        try:
            self.link.remove_callback(self.func, self.msgs)
            self.func.__exit__()
            self.func = None
            self.running = False
        except:
            import traceback
            print traceback.format_exc()
class SbpRelayView(HasTraits):
  """
  UDP Relay view- Class allows user to specify port, IP address, and message set
  to relay over UDP
  """
  running = Bool(False)
  configured = Bool(False)
  broadcasting = Bool(False)
  msg_enum = Enum('Observations', 'All')
  ip_ad = String(DEFAULT_UDP_ADDRESS)
  port = Int(DEFAULT_UDP_PORT)
  information = String('This tab is used to broadcast SBP information received by'
    ' the console to other machines or processes over UDP. With the \'Observations\''
    ' radio button selected, the console will broadcast the necessary information'
    ' for a rover Piksi to acheive an RTK solution.'
    '\n\nThis tab can be used to stream observations to a remote Piksi through'
    ' aircraft telemetry via ground control software such as MAVProxy or'
    ' Mission Planner.')

  start = Button(label='Start', toggle=True, width=32)

  stop = Button(label='Stop', toggle=True, width=32)
  view = View(
          HGroup(
            VGroup(
              Item('running', show_label=True, style='readonly', visible_when='running'),
              Item('msg_enum', label="Messages to broadcast", style='custom',
                   enabled_when='not running'),
              Item('ip_ad', label='IP Address', enabled_when='not running'),
              Item('port', label="Port", enabled_when='not running'),
              HGroup(
                spring,
                UItem('start', enabled_when='not running', show_label=False),
                UItem('stop', enabled_when='running', show_label=False),
                spring
                )
              ),
              VGroup(
                Item('information', label="Notes", height=10,
                editor=MyTextEditor(TextEditor(multi_line=True)), style='readonly',
                show_label=False, resizable=True, padding=15),
                spring,
              ),
            )
          )
  def __init__(self, link):
    """
    Traits tab with UI for UDP broadcast of SBP.

    Parameters
    ----------
    link : sbp.client.handler.Handler
      Link for SBP transfer to/from Piksi.
    """
    self.func = None
    self.msgs = OBS_MSGS
    # register a callback when the msg_enum trait changes
    self.on_trait_change(self.update_msgs, 'msg_enum')
    self.link = link
    self.python_console_cmds = {'update': self}

  def update_msgs(self):
    """
    Updates the instance variable msgs which store the msgs that we will send over UDP
    """
    if self.msg_enum == 'Observations':
      self.msgs = OBS_MSGS
    elif self.msg_enum == 'All':
      self.msgs = [None]
    else:
      raise NotImplementedError

  def _start_fired(self):
    """
    Handle start udp broadcast button. Registers callbacks on self.link for each of the self.msgs
    If self.msgs is None, it registers one generic callback for all messages
    """
    self.running = True
    try:
      self.func = UdpLogger(self.ip_ad, self.port)
      self.link.add_callback(self.func, self.msgs)
    except:
      import traceback
      print traceback.format_exc()

  def _stop_fired(self):
    """
    Handle the stop udp broadcast button. It uses the self.funcs and self.msgs to remove
    the callbacks that were registered when the start button was pressed.
    """
    try:
      self.link.remove_callback(self.func, self.msgs)
      self.func.__exit__()
      self.func = None
      self.running = False
    except:
      import traceback
      print traceback.format_exc()
Exemple #8
0
def test_udp_logger():
  msg = SBP(1, 2, 3, 'abc', 4)
  handler = udp_handler(msg.pack())
  ip, port = udp_server(handler)
  with UdpLogger(ip, port) as udp:
    udp(msg)
class SbpRelayView(HasTraits):
  """
  UDP Relay view- Class allows user to specify port, IP address, and message set
  to relay over UDP
  """
  running = Bool(False)
  configured = Bool(False)
  broadcasting = Bool(False)
  msg_enum = Enum('Observations', 'All')
  ip_ad = String(DEFAULT_UDP_ADDRESS)
  port = Int(DEFAULT_UDP_PORT)
  information = String('UDP Streaming\n\nBroadcast SBP information received by'
    ' the console to other machines or processes over UDP. With the \'Observations\''
    ' radio button selected, the console will broadcast the necessary information'
    ' for a rover Piksi to acheive an RTK solution.'
    '\n\nThis can be used to stream observations to a remote Piksi through'
    ' aircraft telemetry via ground control software such as MAVProxy or'
    ' Mission Planner.')
  http_information = String('Skylark - Experimental Piksi Networking\n\n'
                            "Skylark is Swift Navigation's Internet service for connecting Piksi receivers without the use of a radio. To receive GPS observations from the closest nearby Piksi base station (within 5km), click Connect to Skylark.\n\n")
  start = Button(label='Start', toggle=True, width=32)
  stop = Button(label='Stop', toggle=True, width=32)
  connected_rover = Bool(False)
  connect_rover = Button(label='Connect to Skylark', toggle=True, width=32)
  disconnect_rover = Button(label='Disconnect from Skylark', toggle=True, width=32)
  base_pragma = String()
  rover_pragma = String()
  toggle=True
  view = View(
           VGroup(
             spring,
             HGroup(
               VGroup(
                 Item('running', show_label=True, style='readonly', visible_when='running'),
                 Item('msg_enum', label="Messages to broadcast",
                      style='custom', enabled_when='not running'),
                 Item('ip_ad', label='IP Address', enabled_when='not running'),
                 Item('port', label="Port", enabled_when='not running'),
                 HGroup(
                   spring,
                   UItem('start', enabled_when='not running', show_label=False),
                   UItem('stop', enabled_when='running', show_label=False),
                   spring)),
               VGroup(
                 Item('information', label="Notes", height=10,
                      editor=MultilineTextEditor(TextEditor(multi_line=True)), style='readonly',
                      show_label=False, resizable=True, padding=15),
                 spring,
               ),
             ),
             spring,
             HGroup(
               VGroup(
                 HGroup(
                   spring,
                   UItem('connect_rover', enabled_when='not connected_rover', show_label=False),
                   UItem('disconnect_rover', enabled_when='connected_rover', show_label=False),
                   spring),
                 HGroup(spring,
                        Item('base_pragma',  label='Base option '),
                        spring),
                 HGroup(spring,
                        Item('rover_pragma', label='Rover option'),
                        spring),),
               VGroup(
                 Item('http_information', label="Notes", height=10,
                      editor=MultilineTextEditor(TextEditor(multi_line=True)), style='readonly',
                      show_label=False, resizable=True, padding=15),
                 spring,
               ),
             ),
             spring
           )
  )

  def __init__(self, link, device_uid=None, base=DEFAULT_BASE, whitelist=None):
    """
    Traits tab with UI for UDP broadcast of SBP.

    Parameters
    ----------
    link : sbp.client.handler.Handler
      Link for SBP transfer to/from Piksi.
    device_uid : str
      Piksi Device UUID (defaults to None)
    base : str
      HTTP endpoint
    whitelist : [int] | None
      Piksi Device UUID (defaults to None)

    """
    self.link = link
    self.http = HTTPDriver(None, base)
    self.net_link = None
    self.fwd = None
    self.func = None
    # Whitelist used for UDP broadcast view
    self.msgs = OBS_MSGS
    # register a callback when the msg_enum trait changes
    self.on_trait_change(self.update_msgs, 'msg_enum')
    # Whitelist used for Skylark broadcasting
    self.whitelist = whitelist
    self.device_uid = None
    self.python_console_cmds = {'update': self}

  def update_msgs(self):
    """Updates the instance variable msgs which store the msgs that we
    will send over UDP.

    """
    if self.msg_enum == 'Observations':
      self.msgs = OBS_MSGS
    elif self.msg_enum == 'All':
      self.msgs = [None]
    else:
      raise NotImplementedError

  def set_route(self, serial_id, channel=CHANNEL_UUID):
    """Sets serial_id hash for HTTP headers.

    Parameters
    ----------
    serial_id : int
      Piksi device ID
    channel : str
      UUID namespace for device UUID

    """
    device_uid = str(get_uuid(channel, serial_id))
    self.device_uid = device_uid
    if self.http:
      self.http.device_uid = device_uid

  def _prompt_networking_error(self, text):
    """Nonblocking prompt for a networking error.

    Parameters
    ----------
    text : str
      Helpful error message for the user

    """
    prompt = CallbackPrompt(title="Networking Error", actions=[close_button])
    prompt.text = text
    prompt.run(block=False)

  def _prompt_setting_error(self, text):
    """Nonblocking prompt for a device setting error.

    Parameters
    ----------
    text : str
      Helpful error message for the user

    """
    prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
    prompt.text = text
    prompt.run(block=False)

  def _retry_read(self):
    """Retry read connections. Intended to be called by
    _connect_rover_fired.

    """
    i = 0
    repeats = 5
    _rover_pragma = self.rover_pragma
    while self.http and not self.http.connect_read(pragma=_rover_pragma):
      print "Attempting to read observation from Skylark..."
      time.sleep(0.1)
      i += 1
      if i >= repeats:
        msg = ("\nUnable to receive observations from Skylark!\n\n"
               "Please check that:\n"
               " - you have a network connection\n"
               " - your Piksi has a single-point position\n"
               " - a Skylark-connected Piksi receiver \n   is nearby (within 5km)")
        self._prompt_networking_error(msg)
        self.http.read_close()
        return
    print "Connected as a rover!"
    with Handler(Framer(self.http.read, self.http.write)) as net_link:
      self.net_link = net_link
      self.fwd = Forwarder(net_link, swriter(self.link))
      self.fwd.start()
      while True:
        time.sleep(1)
        if not net_link.is_alive():
          sys.stderr.write("Network observation stream disconnected!")
          break

  def _connect_rover_fired(self):
    """Handle callback for HTTP rover connections.

    """
    if not self.device_uid:
      msg = "\nDevice ID not found!\n\nConnection requires a valid Piksi device ID."
      self._prompt_setting_error(msg)
      return
    if not self.http:
      self._prompt_networking_error("\nNetworking disabled!")
      return
    try:
      _base_pragma = self.base_pragma
      if not self.http.connect_write(self.link, self.whitelist, pragma=_base_pragma):
        msg = ("\nUnable to connect to Skylark!\n\n"
               "Please check that you have a network connection.")
        self._prompt_networking_error(msg)
        self.http.close()
        self.connected_rover = False
        return
      self.connected_rover = True
      print "Connected as a base station!"
      executor = ThreadPoolExecutor(max_workers=2)
      executor.submit(self._retry_read)
    except:
      self.connected_rover = False
      import traceback
      print traceback.format_exc()

  def _disconnect_rover_fired(self):
    """Handle callback for HTTP rover disconnects.

    """
    if not self.device_uid:
      msg = "\nDevice ID not found!\n\nConnection requires a valid Piksi device ID."
      self._prompt_setting_error(msg)
      return
    if not self.http:
      self._prompt_networking_error("\nNetworking disabled!")
      return
    try:
      if self.connected_rover:
        self.http.close()
        self.connected_rover = False
        if self.fwd and self.net_link:
          self.net_link.stop()
    except:
      self.connected_rover = False
      import traceback
      print traceback.format_exc()

  def _start_fired(self):
    """Handle start udp broadcast button. Registers callbacks on
    self.link for each of the self.msgs If self.msgs is None, it
    registers one generic callback for all messages.

    """
    self.running = True
    try:
      self.func = UdpLogger(self.ip_ad, self.port)
      self.link.add_callback(self.func, self.msgs)
    except:
      import traceback
      print traceback.format_exc()

  def _stop_fired(self):
    """Handle the stop udp broadcast button. It uses the self.funcs and
    self.msgs to remove the callbacks that were registered when the
    start button was pressed.

    """
    try:
      self.link.remove_callback(self.func, self.msgs)
      self.func.__exit__()
      self.func = None
      self.running = False
    except:
      import traceback
      print traceback.format_exc()
Exemple #10
0
class SbpRelayView(HasTraits):
  """
  SBP Relay view- Class allows user to specify port, IP address, and message set
  to relay over UDP and to configure a skylark connection
  """
  running = Bool(False)
  configured = Bool(False)
  broadcasting = Bool(False)
  msg_enum = Enum('Observations', 'All')
  ip_ad = String(DEFAULT_UDP_ADDRESS)
  port = Int(DEFAULT_UDP_PORT)
  information = String('UDP Streaming\n\nBroadcast SBP information received by'
    ' the console to other machines or processes over UDP. With the \'Observations\''
    ' radio button selected, the console will broadcast the necessary information'
    ' for a rover Piksi to acheive an RTK solution.'
    '\n\nThis can be used to stream observations to a remote Piksi through'
    ' aircraft telemetry via ground control software such as MAVProxy or'
    ' Mission Planner.')
  http_information = String('Skylark - Experimental Piksi Networking\n\n'
                            "Skylark is Swift Navigation's Internet service for connecting Piksi receivers without the use of a radio. To receive GPS observations from the closest nearby Piksi base station (within 5km), click Connect to Skylark.\n\n")
  start = Button(label='Start', toggle=True, width=32)
  stop = Button(label='Stop', toggle=True, width=32)
  connected_rover = Bool(False)
  connect_rover = Button(label='Connect to Skylark', toggle=True, width=32)
  disconnect_rover = Button(label='Disconnect from Skylark', toggle=True, width=32)
  skylark_url = String()
  base_pragma = String()
  rover_pragma = String()
  base_device_uid = String()
  rover_device_uid = String()
  toggle=True
  view = View(
           VGroup(
             spring,
             HGroup(
               VGroup(
                 Item('running', show_label=True, style='readonly', visible_when='running'),
                 Item('msg_enum', label="Messages to broadcast",
                      style='custom', enabled_when='not running'),
                 Item('ip_ad', label='IP Address', enabled_when='not running'),
                 Item('port', label="Port", enabled_when='not running'),
                 HGroup(
                   spring,
                   UItem('start', enabled_when='not running', show_label=False),
                   UItem('stop', enabled_when='running', show_label=False),
                   spring)),
               VGroup(
                 Item('information', label="Notes", height=10,
                      editor=MultilineTextEditor(TextEditor(multi_line=True)), style='readonly',
                      show_label=False, resizable=True, padding=15),
                 spring,
               ),
             ),
             spring,
             HGroup(
               VGroup(
                 HGroup(
                   spring,
                   UItem('connect_rover', enabled_when='not connected_rover', show_label=False),
                   UItem('disconnect_rover', enabled_when='connected_rover', show_label=False),
                   spring),
                   HGroup(Spring(springy=False, width=2),
                          Item('skylark_url', enabled_when='not connected_rover', show_label=True),
                          Spring(springy=False, width=2)
                          ),
                 HGroup(spring,
                        Item('base_pragma',  label='Base option '),
                        Item('base_device_uid',  label='Base device '),
                        spring),
                 HGroup(spring,
                        Item('rover_pragma', label='Rover option'),
                        Item('rover_device_uid',  label='Rover device'),
                        spring),),
               VGroup(
                 Item('http_information', label="Notes", height=10,
                      editor=MultilineTextEditor(TextEditor(multi_line=True)), style='readonly',
                      show_label=False, resizable=True, padding=15),
                 spring,
               ),
             ),
             spring
           )
  )

  def __init__(self, link, device_uid=None, base=DEFAULT_BASE, 
               whitelist=None, rover_pragma='', base_pragma='', rover_uuid='', base_uuid='',
               connect=False, verbose=False):
    """
    Traits tab with UI for UDP broadcast of SBP.

    Parameters
    ----------
    link : sbp.client.handler.Handler
      Link for SBP transfer to/from Piksi.
    device_uid : str
      Piksi Device UUID (defaults to None)
    base : str
      HTTP endpoint
    whitelist : [int] | None
      Piksi Device UUID (defaults to None)

    """
    self.link = link
    # Whitelist used for UDP broadcast view
    self.msgs = OBS_MSGS
    # register a callback when the msg_enum trait changes
    self.on_trait_change(self.update_msgs, 'msg_enum')
    # Whitelist used for Skylark broadcasting
    self.whitelist = whitelist
    self.device_uid = None
    self.python_console_cmds = {'update': self}
    self.rover_pragma = rover_pragma
    self.base_pragma = base_pragma
    self.rover_device_uid = rover_uuid
    self.base_device_uid = base_uuid
    self.verbose = verbose
    self.skylark_watchdog_thread = None
    self.skylark_url = base
    if connect:
      self.connect_when_uuid_received = True
    else:
      self.connect_when_uuid_received = False

  def update_msgs(self):
    """Updates the instance variable msgs which store the msgs that we
    will send over UDP.

    """
    if self.msg_enum == 'Observations':
      self.msgs = OBS_MSGS
    elif self.msg_enum == 'All':
      self.msgs = [None]
    else:
      raise NotImplementedError

  def set_route(self, uuid=None, serial_id=None, channel=CHANNEL_UUID):
    """Sets serial_id hash for HTTP headers.

    Parameters
    ----------
    uuid: str
      real uuid of device
    serial_id : int
      Piksi device ID
    channel : str
      UUID namespace for device UUID

    """
    if uuid:
      device_uid = uuid
    elif serial_id:
      device_uid = str(get_uuid(channel, serial_id % 1000))
    else:
      print("Improper call of set_route, either a serial number or UUID should be passed")
      device_uid = str(get_uuid(channel, 1234))
      print(("Setting UUID to default value of {0}".format(device_uid)))
    self.device_uid = device_uid

  def _prompt_setting_error(self, text):
    """Nonblocking prompt for a device setting error.

    Parameters
    ----------
    text : str
      Helpful error message for the user

    """
    prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
    prompt.text = text
    prompt.run(block=False)

  def _disconnect_rover_fired(self):
    """Handle callback for HTTP rover disconnects.

    """
    try:
      if isinstance(self.skylark_watchdog_thread, threading.Thread) and \
         not self.skylark_watchdog_thread.stopped():
        self.skylark_watchdog_thread.stop()
      else:
        print((("Unable to disconnect: Skylark watchdog thread "
               "inititalized at {0} and connected since {1} has " 
               "already been stopped").format(self.skylark_watchdog_thread.get_init_time(),
                                              self.skylark_watchdog_thread.get_connect_time())))
      self.connected_rover = False
    except:
      self.connected_rover = False
      import traceback
      print((traceback.format_exc()))

  def _connect_rover_fired(self):
    """Handle callback for HTTP rover connections.  Launches an instance of skylark_watchdog_thread.
    """
    if not self.device_uid:
      msg = "\nDevice ID not found!\n\nConnection requires a valid Piksi device ID."
      self._prompt_setting_error(msg)
      return
    try:
      _base_device_uid = self.base_device_uid or self.device_uid
      _rover_device_uid = self.rover_device_uid or self.device_uid
      config = SkylarkConsoleConnectConfig(self.link, self.device_uid, 
               self.skylark_url, self.whitelist, self.rover_pragma, 
               self.base_pragma, _rover_device_uid, _base_device_uid)
      self.skylark_watchdog_thread = SkylarkWatchdogThread(link=self.link, skylark_config=config, 
                                        stopped_callback=self._disconnect_rover_fired,
                                        verbose=self.verbose)
      self.connected_rover = True
      self.skylark_watchdog_thread.start()
    except:
      if isinstance(self.skylark_watchdog_thread, threading.Thread) \
         and self.skylark_watchdog_thread.stopped():
        self.skylark_watchdog_thread.stop()
      self.connected_rover = False
      import traceback
      print((traceback.format_exc()))

  def _start_fired(self):
    """Handle start udp broadcast button. Registers callbacks on
    self.link for each of the self.msgs If self.msgs is None, it
    registers one generic callback for all messages.

    """
    self.running = True
    try:
      self.func = UdpLogger(self.ip_ad, self.port)
      self.link.add_callback(self.func, self.msgs)
    except:
      import traceback
      print((traceback.format_exc()))

  def _stop_fired(self):
    """Handle the stop udp broadcast button. It uses the self.funcs and
    self.msgs to remove the callbacks that were registered when the
    start button was pressed.

    """
    try:
      self.link.remove_callback(self.func, self.msgs)
      self.func.__exit__()
      self.func = None
      self.running = False
    except:
      import traceback
      print((traceback.format_exc()))
NTRIP_HOST = rospy.get_param('/ntrip_host', "rtk2go.com")
NTRIP_PORT = rospy.get_param('/ntrip_port', 2101)
NTRIP_MOUNT_POINT = rospy.get_param('/ntrip_mount_point', "ER_Valldoreix_1")
#RADIO
RADIO_PORT = rospy.get_param('/sbp_arbitrator/radio_port',
                             "/dev/freewaveGXMT14")
RADIO_BAUDRATE = rospy.get_param('/sbp_arbitrator/radio_baudrate', 115200)
# UDP LOGGER
UDP_ADDRESS = rospy.get_param('/sbp_arbitrator/udp_address', "192.168.8.222")
UDP_PORT = rospy.get_param('/sbp_arbitrator/udp_port', 55558)

freq = rospy.get_param('/sbp_arbitrator/frequency', 5)
debug = rospy.get_param('/sbp_arbitrator/debug', False)

# create instance of UdpLogger object
udp = UdpLogger(UDP_ADDRESS, UDP_PORT)

# txt files for msg logging
if debug:
    HOME = os.getenv('HOME')
    now = datetime.datetime.utcnow()
    txt_time = now.strftime("%Y%m%d%H%M%S")
    ntrip_file_path = HOME + "/sbp_arb_logs/" + txt_time + "_ntrip.txt"
    radio_file_path = HOME + "/sbp_arb_logs/" + txt_time + "_radio.txt"
    arb_file_path = HOME + "/sbp_arb_logs/" + txt_time + "_arbitrator.txt"
    ntrip_txt_file = open(ntrip_file_path, "a")
    radio_txt_file = open(radio_file_path, "a")
    arb_txt_file = open(arb_file_path, "a")


# get current year:month:day:hour
Exemple #12
0
class SbpRelayView(HasTraits):
    """
    SBP Relay view- Class allows user to specify port, IP address, and message set
    to relay over UDP and to configure a http connection
    """
    running = Bool(False)
    _network_info = List()
    configured = Bool(False)
    broadcasting = Bool(False)
    msg_enum = Enum('Observations', 'All')
    ip_ad = String(DEFAULT_UDP_ADDRESS)
    port = Int(DEFAULT_UDP_PORT)
    information = String(
        'UDP Streaming\n\nBroadcast SBP information received by'
        ' the console to other machines or processes over UDP. With the \'Observations\''
        ' radio button selected, the console will broadcast the necessary information'
        ' for a rover Piksi to acheive an RTK solution.'
        '\n\nThis can be used to stream observations to a remote Piksi through'
        ' aircraft telemetry via ground control software such as MAVProxy or'
        ' Mission Planner.')
    show_networking = Bool(False)
    http_information = String(
        'Experimental Piksi Networking\n\n'
        "Use this widget to connect Piksi receivers to http servers.\n\n")
    start = Button(label='Start', toggle=True, width=32)
    stop = Button(label='Stop', toggle=True, width=32)
    connected_rover = Bool(False)
    connect_rover = Button(label='Connect', toggle=True, width=32)
    disconnect_rover = Button(label='Disconnect', toggle=True, width=32)
    url = String()
    base_pragma = String()
    rover_pragma = String()
    base_device_uid = String()
    rover_device_uid = String()
    toggle = True
    network_refresh_button = SVGButton(
        label='Refresh Network Status',
        tooltip='Refresh Network Status',
        filename=resource_filename('console/images/fontawesome/refresh.svg'),
        width=16,
        height=16,
        aligment='center')
    cell_modem_view = Instance(CellModemView)
    view = View(
        VGroup(
            spring,
            HGroup(VGroup(
                Item('msg_enum',
                     label="Messages to broadcast",
                     style='custom',
                     enabled_when='not running'),
                Item('ip_ad', label='IP Address', enabled_when='not running'),
                Item('port', label="Port", enabled_when='not running'),
                HGroup(
                    spring,
                    UItem('start',
                          enabled_when='not running',
                          show_label=False),
                    UItem('stop', enabled_when='running', show_label=False),
                    spring)),
                   VGroup(
                       Item('information',
                            label="Notes",
                            height=10,
                            editor=MultilineTextEditor(
                                TextEditor(multi_line=True)),
                            style='readonly',
                            show_label=False,
                            resizable=True,
                            padding=15),
                       spring,
                   ),
                   visible_when='not show_networking'), spring,
            HGroup(VGroup(
                HGroup(
                    spring,
                    UItem('connect_rover',
                          enabled_when='not connected_rover',
                          show_label=False),
                    UItem('disconnect_rover',
                          enabled_when='connected_rover',
                          show_label=False), spring),
                HGroup(
                    Spring(springy=False, width=2),
                    Item('url',
                         enabled_when='not connected_rover',
                         show_label=True), Spring(springy=False, width=2)),
                HGroup(spring, Item('base_pragma', label='Base option '),
                       Item('base_device_uid', label='Base device '), spring),
                HGroup(spring, Item('rover_pragma', label='Rover option'),
                       Item('rover_device_uid', label='Rover device'), spring),
            ),
                   VGroup(
                       Item('http_information',
                            label="Notes",
                            height=10,
                            editor=MultilineTextEditor(
                                TextEditor(multi_line=True)),
                            style='readonly',
                            show_label=False,
                            resizable=True,
                            padding=15),
                       spring,
                   ),
                   visible_when='show_networking'),
            HGroup(
                Item('cell_modem_view', style='custom', show_label=False),
                VGroup(Item(
                    '_network_info',
                    style='readonly',
                    editor=TabularEditor(adapter=SimpleNetworkAdapter()),
                    show_label=False,
                ),
                       Item('network_refresh_button',
                            show_label=False,
                            width=0.50),
                       show_border=True,
                       label="Network"),
            )))

    def _network_callback(self, m, **metadata):
        txstr = sizeof_fmt(m.tx_bytes),
        rxstr = sizeof_fmt(m.rx_bytes)
        if m.interface_name.startswith(
                'ppp0'):  # Hack for ppp tx and rx which doesn't work
            txstr = "---"
            rxstr = "---"
        elif m.interface_name.startswith('lo') or m.interface_name.startswith(
                'sit0'):
            return
        table_row = ((m.interface_name, ip_bytes_to_string(m.ipv4_address),
                      ((m.flags & (1 << 6)) != 0), txstr, rxstr))
        exists = False
        for i, each in enumerate(self._network_info):
            if each[0][0] == table_row[0][0]:
                self._network_info[i] = table_row
                exists = True
        if not exists:
            self._network_info.append(table_row)

    def __init__(self,
                 link,
                 show_networking=False,
                 device_uid=None,
                 url='',
                 whitelist=None,
                 rover_pragma='',
                 base_pragma='',
                 rover_uuid='',
                 base_uuid='',
                 connect=False,
                 verbose=False):
        """
        Traits tab with UI for UDP broadcast of SBP.

        Parameters
        ----------
        link : sbp.client.handler.Handler
          Link for SBP transfer to/from Piksi.
        device_uid : str
          Piksi Device UUID (defaults to None)
        base : str
          HTTP endpoint
        whitelist : [int] | None
          Piksi Device UUID (defaults to None)

        """
        self.link = link
        # Whitelist used for UDP broadcast view
        self.cell_modem_view = CellModemView(link)
        self.msgs = OBS_MSGS
        # register a callback when the msg_enum trait changes
        self.on_trait_change(self.update_msgs, 'msg_enum')
        # Whitelist used for broadcasting
        self.whitelist = whitelist
        self.device_uid = None
        self.python_console_cmds = {'update': self}
        self.rover_pragma = rover_pragma
        self.base_pragma = base_pragma
        self.rover_device_uid = rover_uuid
        self.base_device_uid = base_uuid
        self.verbose = verbose
        self.http_watchdog_thread = None
        self.url = url
        self.show_networking = show_networking
        if connect:
            self.connect_when_uuid_received = True
        else:
            self.connect_when_uuid_received = False
        self.cellmodem_interface_name = "ppp0"
        self.link.add_callback(self._network_callback,
                               SBP_MSG_NETWORK_STATE_RESP)

    def update_msgs(self):
        """Updates the instance variable msgs which store the msgs that we
        will send over UDP.

        """
        if self.msg_enum == 'Observations':
            self.msgs = OBS_MSGS
        elif self.msg_enum == 'All':
            self.msgs = [None]
        else:
            raise NotImplementedError

    def set_route(self, uuid=None, serial_id=None, channel=CHANNEL_UUID):
        """Sets serial_id hash for HTTP headers.

        Parameters
        ----------
        uuid: str
          real uuid of device
        serial_id : int
          Piksi device ID
        channel : str
          UUID namespace for device UUID

        """
        if uuid:
            device_uid = uuid
        elif serial_id:
            device_uid = str(get_uuid(channel, serial_id % 1000))
        else:
            print(
                "Improper call of set_route, either a serial number or UUID should be passed"
            )
            device_uid = str(get_uuid(channel, 1234))
            print("Setting UUID to default value of {0}".format(device_uid))
        self.device_uid = device_uid

    def _prompt_setting_error(self, text):
        """Nonblocking prompt for a device setting error.

        Parameters
        ----------
        text : str
          Helpful error message for the user

        """
        prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
        prompt.text = text
        prompt.run(block=False)

    def update_network_state(self):
        self._network_refresh_button_fired()

    def _network_refresh_button_fired(self):
        self._network_info = []
        self.link(MsgNetworkStateReq())

    def _disconnect_rover_fired(self):
        """Handle callback for HTTP rover disconnects.

        """
        try:
            if (isinstance(self.http_watchdog_thread, threading.Thread)
                    and not self.http_watchdog_thread.stopped()):
                self.http_watchdog_thread.stop()
            else:
                print(("Unable to disconnect: Http watchdog thread "
                       "inititalized at {0} and connected since {1} has "
                       "already been stopped").format(
                           self.http_watchdog_thread.get_init_time(),
                           self.http_watchdog_thread.get_connect_time()))
            self.connected_rover = False
        except:  # noqa
            self.connected_rover = False
            import traceback
            print(traceback.format_exc())

    def _connect_rover_fired(self):
        """Handle callback for HTTP rover connections.  Launches an instance of http_watchdog_thread.
        """
        if not self.device_uid:
            msg = "\nDevice ID not found!\n\nConnection requires a valid Piksi device ID."
            self._prompt_setting_error(msg)
            return
        try:
            _base_device_uid = self.base_device_uid or self.device_uid
            _rover_device_uid = self.rover_device_uid or self.device_uid
            config = HttpConsoleConnectConfig(self.link, self.device_uid,
                                              self.url, self.whitelist,
                                              self.rover_pragma,
                                              self.base_pragma,
                                              _rover_device_uid,
                                              _base_device_uid)
            self.http_watchdog_thread = HttpWatchdogThread(
                link=self.link,
                http_config=config,
                stopped_callback=self._disconnect_rover_fired,
                verbose=self.verbose)
            self.connected_rover = True
            self.http_watchdog_thread.start()
        except:  # noqa
            if (isinstance(self.http_watchdog_thread, threading.Thread)
                    and self.http_watchdog_thread.stopped()):
                self.http_watchdog_thread.stop()
            self.connected_rover = False
            import traceback
            print(traceback.format_exc())

    def _start_fired(self):
        """Handle start udp broadcast button. Registers callbacks on
        self.link for each of the self.msgs If self.msgs is None, it
        registers one generic callback for all messages.

        """
        self.running = True
        try:
            self.func = UdpLogger(self.ip_ad, self.port)
            self.link.add_callback(self.func, self.msgs)
        except:  # noqa
            import traceback
            print(traceback.format_exc())

    def _stop_fired(self):
        """Handle the stop udp broadcast button. It uses the self.funcs and
        self.msgs to remove the callbacks that were registered when the
        start button was pressed.

        """
        try:
            self.link.remove_callback(self.func, self.msgs)
            self.func.__exit__()
            self.func = None
            self.running = False
        except:  # noqa
            import traceback
            print(traceback.format_exc())
class SbpRelayView(HasTraits):
    """
    Class allows user to specify port, IP address, and message set
    to relay over UDP.
    """
    running = Bool(False)
    _network_info = List()
    configured = Bool(False)
    broadcasting = Bool(False)
    msg_enum = Enum('Observations', 'All')
    ip_ad = String(DEFAULT_UDP_ADDRESS)
    port = Int(DEFAULT_UDP_PORT)
    information = String(
        'UDP Streaming\n\nBroadcast SBP information received by'
        ' the console to other machines or processes over UDP. With the \'Observations\''
        ' radio button selected, the console will broadcast the necessary information'
        ' for a rover Piksi to acheive an RTK solution.'
        '\n\nThis can be used to stream observations to a remote Piksi through'
        ' aircraft telemetry via ground control software such as MAVProxy or'
        ' Mission Planner.')
    start = Button(label='Start', toggle=True, width=32)
    stop = Button(label='Stop', toggle=True, width=32)
    network_refresh_button = SVGButton(
        label='Refresh Network Status',
        tooltip='Refresh Network Status',
        filename=resource_filename('console/images/fontawesome/refresh.svg'),
        width=16,
        height=16,
        aligment='center')
    cell_modem_view = Instance(CellModemView)
    view = View(
        VGroup(spring,
               HGroup(
                   VGroup(
                       Item(
                           'msg_enum',
                           label="Messages to broadcast",
                           style='custom',
                           enabled_when='not running'),
                       Item(
                           'ip_ad',
                           label='IP Address',
                           enabled_when='not running'),
                       Item('port', label="Port", enabled_when='not running'),
                       HGroup(spring,
                              UItem(
                                  'start',
                                  enabled_when='not running',
                                  show_label=False),
                              UItem(
                                  'stop',
                                  enabled_when='running',
                                  show_label=False), spring)),
                   VGroup(
                       Item(
                           'information',
                           label="Notes",
                           height=10,
                           editor=MultilineTextEditor(
                               TextEditor(multi_line=True)),
                           style='readonly',
                           show_label=False,
                           resizable=True,
                           padding=15),
                       spring,
                   )
               ),
               spring,
               HGroup(Item('cell_modem_view', style='custom', show_label=False),
                      VGroup(
                          Item(
                              '_network_info',
                              style='readonly',
                              editor=TabularEditor(
                                  adapter=SimpleNetworkAdapter()),
                              show_label=False, ),
                          Item(
                              'network_refresh_button', show_label=False,
                              width=0.50),
                          show_border=True,
                          label="Network"),
                      )
               )
    )

    def _network_callback(self, m, **metadata):
        txstr = sizeof_fmt(m.tx_bytes),
        rxstr = sizeof_fmt(m.rx_bytes)
        if m.interface_name.startswith(b'ppp0'):  # Hack for ppp tx and rx which doesn't work
            txstr = "---"
            rxstr = "---"
        elif m.interface_name.startswith(b'lo') or m.interface_name.startswith(b'sit0'):
            return
        table_row = ((m.interface_name.decode('ascii'), ip_bytes_to_string(m.ipv4_address),
                     ((m.flags & (1 << 6)) != 0), txstr, rxstr))
        exists = False
        for i, each in enumerate(self._network_info):
            if each[0][0] == table_row[0][0]:
                self._network_info[i] = table_row
                exists = True
        if not exists:
            self._network_info.append(table_row)

    def __init__(self,
                 link):
        """
        Traits tab with UI for UDP broadcast of SBP.

        Parameters
        ----------
        link : sbp.client.handler.Handler
          Link for SBP transfer to/from Piksi.
        device_uid : str
          Piksi Device UUID (defaults to None)
        whitelist : [int] | None
          Piksi Device UUID (defaults to None)

        """
        self.link = link
        # Whitelist used for UDP broadcast view
        self.cell_modem_view = CellModemView(link)
        self.msgs = OBS_MSGS
        # register a callback when the msg_enum trait changes
        self.on_trait_change(self.update_msgs, 'msg_enum')
        self.python_console_cmds = {'update': self}
        self.cellmodem_interface_name = "ppp0"
        self.link.add_callback(self._network_callback,
                               SBP_MSG_NETWORK_STATE_RESP)

    def update_msgs(self):
        """Updates the instance variable msgs which store the msgs that we
        will send over UDP.

        """
        if self.msg_enum == 'Observations':
            self.msgs = OBS_MSGS
        elif self.msg_enum == 'All':
            self.msgs = [None]
        else:
            raise NotImplementedError

    def _prompt_setting_error(self, text):
        """Nonblocking prompt for a device setting error.

        Parameters
        ----------
        text : str
          Helpful error message for the user

        """
        prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
        prompt.text = text
        prompt.run(block=False)

    def update_network_state(self):
        self._network_refresh_button_fired()

    def _network_refresh_button_fired(self):
        self._network_info = []
        self.link(MsgNetworkStateReq())

    def _start_fired(self):
        """Handle start udp broadcast button. Registers callbacks on
        self.link for each of the self.msgs If self.msgs is None, it
        registers one generic callback for all messages.

        """
        self.running = True
        try:
            self.func = UdpLogger(self.ip_ad, self.port)
            self.link.add_callback(self.func, self.msgs)
        except:  # noqa
            import traceback
            print(traceback.format_exc())

    def _stop_fired(self):
        """Handle the stop udp broadcast button. It uses the self.funcs and
        self.msgs to remove the callbacks that were registered when the
        start button was pressed.

        """
        try:
            self.link.remove_callback(self.func, self.msgs)
            self.func.__exit__()
            self.func = None
            self.running = False
        except:  # noqa
            import traceback
            print(traceback.format_exc())
class SbpRelayView(HasTraits):
    """
    SBP Relay view- Class allows user to specify port, IP address, and message set
    to relay over UDP and to configure a http connection
    """
    running = Bool(False)
    configured = Bool(False)
    broadcasting = Bool(False)
    msg_enum = Enum('Observations', 'All')
    ip_ad = String(DEFAULT_UDP_ADDRESS)
    port = Int(DEFAULT_UDP_PORT)
    information = String(
        'UDP Streaming\n\nBroadcast SBP information received by'
        ' the console to other machines or processes over UDP. With the \'Observations\''
        ' radio button selected, the console will broadcast the necessary information'
        ' for a rover Piksi to acheive an RTK solution.'
        '\n\nThis can be used to stream observations to a remote Piksi through'
        ' aircraft telemetry via ground control software such as MAVProxy or'
        ' Mission Planner.')
    show_networking = Bool(False)
    http_information = String(
        'Experimental Piksi Networking\n\n'
        "Use this widget to connect Piksi receivers to http servers.\n\n")
    start = Button(label='Start', toggle=True, width=32)
    stop = Button(label='Stop', toggle=True, width=32)
    connected_rover = Bool(False)
    connect_rover = Button(label='Connect', toggle=True, width=32)
    disconnect_rover = Button(label='Disconnect', toggle=True, width=32)
    url = String()
    base_pragma = String()
    rover_pragma = String()
    base_device_uid = String()
    rover_device_uid = String()
    toggle = True
    view = View(
        VGroup(spring,
               HGroup(
                   VGroup(
                       Item(
                           'running',
                           show_label=True,
                           style='readonly',
                           visible_when='running'),
                       Item(
                           'msg_enum',
                           label="Messages to broadcast",
                           style='custom',
                           enabled_when='not running'),
                       Item(
                           'ip_ad',
                           label='IP Address',
                           enabled_when='not running'),
                       Item('port', label="Port", enabled_when='not running'),
                       HGroup(spring,
                              UItem(
                                  'start',
                                  enabled_when='not running',
                                  show_label=False),
                              UItem(
                                  'stop',
                                  enabled_when='running',
                                  show_label=False), spring)),
                   VGroup(
                       Item(
                           'information',
                           label="Notes",
                           height=10,
                           editor=MultilineTextEditor(
                               TextEditor(multi_line=True)),
                           style='readonly',
                           show_label=False,
                           resizable=True,
                           padding=15),
                       spring, ), ), spring,
               HGroup(
                   VGroup(
                       HGroup(spring,
                              UItem(
                                  'connect_rover',
                                  enabled_when='not connected_rover',
                                  show_label=False),
                              UItem(
                                  'disconnect_rover',
                                  enabled_when='connected_rover',
                                  show_label=False), spring),
                       HGroup(
                           Spring(springy=False, width=2),
                           Item(
                               'url',
                               enabled_when='not connected_rover',
                               show_label=True), Spring(
                                   springy=False, width=2)),
                       HGroup(spring,
                              Item('base_pragma', label='Base option '),
                              Item('base_device_uid', label='Base device '),
                              spring),
                       HGroup(spring,
                              Item('rover_pragma', label='Rover option'),
                              Item('rover_device_uid', label='Rover device'),
                              spring), ),
                   VGroup(
                       Item(
                           'http_information',
                           label="Notes",
                           height=10,
                           editor=MultilineTextEditor(
                               TextEditor(multi_line=True)),
                           style='readonly',
                           show_label=False,
                           resizable=True,
                           padding=15),
                       spring, ),
                   visible_when='show_networking', ), spring))

    def __init__(self,
                 link,
                 show_networking=False,
                 device_uid=None,
                 url='',
                 whitelist=None,
                 rover_pragma='',
                 base_pragma='',
                 rover_uuid='',
                 base_uuid='',
                 connect=False,
                 verbose=False):
        """
        Traits tab with UI for UDP broadcast of SBP.

        Parameters
        ----------
        link : sbp.client.handler.Handler
          Link for SBP transfer to/from Piksi.
        device_uid : str
          Piksi Device UUID (defaults to None)
        base : str
          HTTP endpoint
        whitelist : [int] | None
          Piksi Device UUID (defaults to None)

        """
        self.link = link
        # Whitelist used for UDP broadcast view
        self.msgs = OBS_MSGS
        # register a callback when the msg_enum trait changes
        self.on_trait_change(self.update_msgs, 'msg_enum')
        # Whitelist used for broadcasting
        self.whitelist = whitelist
        self.device_uid = None
        self.python_console_cmds = {'update': self}
        self.rover_pragma = rover_pragma
        self.base_pragma = base_pragma
        self.rover_device_uid = rover_uuid
        self.base_device_uid = base_uuid
        self.verbose = verbose
        self.http_watchdog_thread = None
        self.url = url
        self.show_networking = show_networking
        if connect:
            self.connect_when_uuid_received = True
        else:
            self.connect_when_uuid_received = False

    def update_msgs(self):
        """Updates the instance variable msgs which store the msgs that we
        will send over UDP.

        """
        if self.msg_enum == 'Observations':
            self.msgs = OBS_MSGS
        elif self.msg_enum == 'All':
            self.msgs = [None]
        else:
            raise NotImplementedError

    def set_route(self, uuid=None, serial_id=None, channel=CHANNEL_UUID):
        """Sets serial_id hash for HTTP headers.

        Parameters
        ----------
        uuid: str
          real uuid of device
        serial_id : int
          Piksi device ID
        channel : str
          UUID namespace for device UUID

        """
        if uuid:
            device_uid = uuid
        elif serial_id:
            device_uid = str(get_uuid(channel, serial_id % 1000))
        else:
            print(
                "Improper call of set_route, either a serial number or UUID should be passed"
            )
            device_uid = str(get_uuid(channel, 1234))
            print("Setting UUID to default value of {0}".format(device_uid))
        self.device_uid = device_uid

    def _prompt_setting_error(self, text):
        """Nonblocking prompt for a device setting error.

        Parameters
        ----------
        text : str
          Helpful error message for the user

        """
        prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
        prompt.text = text
        prompt.run(block=False)

    def _disconnect_rover_fired(self):
        """Handle callback for HTTP rover disconnects.

        """
        try:
            if isinstance(self.http_watchdog_thread, threading.Thread) and \
               not self.http_watchdog_thread.stopped():
                self.http_watchdog_thread.stop()
            else:
                print(("Unable to disconnect: Http watchdog thread "
                       "inititalized at {0} and connected since {1} has "
                       "already been stopped").format(
                           self.http_watchdog_thread.get_init_time(),
                           self.http_watchdog_thread.get_connect_time()))
            self.connected_rover = False
        except:
            self.connected_rover = False
            import traceback
            print(traceback.format_exc())

    def _connect_rover_fired(self):
        """Handle callback for HTTP rover connections.  Launches an instance of http_watchdog_thread.
        """
        if not self.device_uid:
            msg = "\nDevice ID not found!\n\nConnection requires a valid Piksi device ID."
            self._prompt_setting_error(msg)
            return
        try:
            _base_device_uid = self.base_device_uid or self.device_uid
            _rover_device_uid = self.rover_device_uid or self.device_uid
            config = HttpConsoleConnectConfig(
                self.link, self.device_uid, self.url, self.whitelist,
                self.rover_pragma, self.base_pragma, _rover_device_uid,
                _base_device_uid)
            self.http_watchdog_thread = HttpWatchdogThread(
                link=self.link,
                http_config=config,
                stopped_callback=self._disconnect_rover_fired,
                verbose=self.verbose)
            self.connected_rover = True
            self.http_watchdog_thread.start()
        except:
            if isinstance(self.http_watchdog_thread, threading.Thread) \
               and self.http_watchdog_thread.stopped():
                self.http_watchdog_thread.stop()
            self.connected_rover = False
            import traceback
            print(traceback.format_exc())

    def _start_fired(self):
        """Handle start udp broadcast button. Registers callbacks on
        self.link for each of the self.msgs If self.msgs is None, it
        registers one generic callback for all messages.

        """
        self.running = True
        try:
            self.func = UdpLogger(self.ip_ad, self.port)
            self.link.add_callback(self.func, self.msgs)
        except:
            import traceback
            print(traceback.format_exc())

    def _stop_fired(self):
        """Handle the stop udp broadcast button. It uses the self.funcs and
        self.msgs to remove the callbacks that were registered when the
        start button was pressed.

        """
        try:
            self.link.remove_callback(self.func, self.msgs)
            self.func.__exit__()
            self.func = None
            self.running = False
        except:
            import traceback
            print(traceback.format_exc())
Exemple #15
0
class SbpRelayView(HasTraits):
    """
    Class allows user to specify port, IP address, and message set
    to relay over UDP.
    """
    running = Bool(False)
    _network_info = List()
    configured = Bool(False)
    broadcasting = Bool(False)
    msg_enum = Enum('Observations', 'All')
    ip_ad = String(DEFAULT_UDP_ADDRESS)
    port = Int(DEFAULT_UDP_PORT)
    information = String(
        'UDP Streaming\n\nBroadcast SBP information received by'
        ' the console to other machines or processes over UDP. With the \'Observations\''
        ' radio button selected, the console will broadcast the necessary information'
        ' for a rover Piksi to acheive an RTK solution.'
        '\n\nThis can be used to stream observations to a remote Piksi through'
        ' aircraft telemetry via ground control software such as MAVProxy or'
        ' Mission Planner.')
    start = Button(label='Start', toggle=True, width=32)
    stop = Button(label='Stop', toggle=True, width=32)
    network_refresh_button = SVGButton(
        label='Refresh Network Status',
        tooltip='Refresh Network Status',
        filename=resource_filename('console/images/fontawesome/refresh.svg'),
        width=16,
        height=16,
        aligment='center')
    cell_modem_view = Instance(CellModemView)
    view = View(
        VGroup(
            spring,
            HGroup(
                VGroup(
                    Item('msg_enum',
                         label="Messages to broadcast",
                         style='custom',
                         enabled_when='not running'),
                    Item('ip_ad',
                         label='IP Address',
                         enabled_when='not running'),
                    Item('port', label="Port", enabled_when='not running'),
                    HGroup(
                        spring,
                        UItem('start',
                              enabled_when='not running',
                              show_label=False),
                        UItem('stop', enabled_when='running',
                              show_label=False), spring)),
                VGroup(
                    Item('information',
                         label="Notes",
                         height=10,
                         editor=MultilineTextEditor(
                             TextEditor(multi_line=True)),
                         style='readonly',
                         show_label=False,
                         resizable=True,
                         padding=15),
                    spring,
                )), spring,
            HGroup(
                Item('cell_modem_view', style='custom', show_label=False),
                VGroup(Item(
                    '_network_info',
                    style='readonly',
                    editor=TabularEditor(adapter=SimpleNetworkAdapter()),
                    show_label=False,
                ),
                       Item('network_refresh_button',
                            show_label=False,
                            width=0.50),
                       show_border=True,
                       label="Network"),
            )))

    def _network_callback(self, m, **metadata):
        txstr = sizeof_fmt(m.tx_bytes),
        rxstr = sizeof_fmt(m.rx_bytes)
        if m.interface_name.startswith(
                b'ppp0'):  # Hack for ppp tx and rx which doesn't work
            txstr = "---"
            rxstr = "---"
        elif m.interface_name.startswith(b'lo') or m.interface_name.startswith(
                b'sit0'):
            return
        table_row = ((m.interface_name.decode('ascii'),
                      ip_bytes_to_string(m.ipv4_address),
                      ((m.flags & (1 << 6)) != 0), txstr, rxstr))
        exists = False
        for i, each in enumerate(self._network_info):
            if each[0][0] == table_row[0][0]:
                self._network_info[i] = table_row
                exists = True
        if not exists:
            self._network_info.append(table_row)

    def __init__(self, link):
        """
        Traits tab with UI for UDP broadcast of SBP.

        Parameters
        ----------
        link : sbp.client.handler.Handler
          Link for SBP transfer to/from Piksi.
        device_uid : str
          Piksi Device UUID (defaults to None)
        whitelist : [int] | None
          Piksi Device UUID (defaults to None)

        """
        self.link = link
        # Whitelist used for UDP broadcast view
        self.cell_modem_view = CellModemView(link)
        self.msgs = OBS_MSGS
        # register a callback when the msg_enum trait changes
        self.on_trait_change(self.update_msgs, 'msg_enum')
        self.python_console_cmds = {'update': self}
        self.cellmodem_interface_name = "ppp0"
        self.link.add_callback(self._network_callback,
                               SBP_MSG_NETWORK_STATE_RESP)

    def update_msgs(self):
        """Updates the instance variable msgs which store the msgs that we
        will send over UDP.

        """
        if self.msg_enum == 'Observations':
            self.msgs = OBS_MSGS
        elif self.msg_enum == 'All':
            self.msgs = [None]
        else:
            raise NotImplementedError

    def _prompt_setting_error(self, text):
        """Nonblocking prompt for a device setting error.

        Parameters
        ----------
        text : str
          Helpful error message for the user

        """
        prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
        prompt.text = text
        prompt.run(block=False)

    def update_network_state(self):
        self._network_refresh_button_fired()

    def _network_refresh_button_fired(self):
        self._network_info = []
        self.link(MsgNetworkStateReq())

    def _start_fired(self):
        """Handle start udp broadcast button. Registers callbacks on
        self.link for each of the self.msgs If self.msgs is None, it
        registers one generic callback for all messages.

        """
        self.running = True
        try:
            self.func = UdpLogger(self.ip_ad, self.port)
            self.link.add_callback(self.func, self.msgs)
        except:  # noqa
            import traceback
            print(traceback.format_exc())

    def _stop_fired(self):
        """Handle the stop udp broadcast button. It uses the self.funcs and
        self.msgs to remove the callbacks that were registered when the
        start button was pressed.

        """
        try:
            self.link.remove_callback(self.func, self.msgs)
            self.func.__exit__()
            self.func = None
            self.running = False
        except:  # noqa
            import traceback
            print(traceback.format_exc())