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 test_http_test_pass(): assert is_enabled() msg = MsgPrintDep(text='abcd') register_uri(GET, BASE_STATION_URI, msg.to_binary(), content_type="application/vnd.swiftnav.broker.v1+sbp2") register_uri(PUT, BASE_STATION_URI, '', content_type="application/vnd.swiftnav.broker.v1+sbp2") with HTTPDriver(device_uid="Swift22", url=BASE_STATION_URI) as driver: assert not driver.read_ok assert driver.connect_read() assert driver.read_ok assert driver.read(size=255) == msg.to_binary() with pytest.raises(IOError): assert driver.read(size=255) assert not driver.read_close() assert driver.read_response is None assert not driver.read_ok with pytest.raises(ValueError): driver.read(size=255) with HTTPDriver(device_uid="Swift22", url=BASE_STATION_URI) as http: with Handler(Framer(http.read, http.write, False)) as link: def tester(sbp_msg, **metadata): assert sbp_msg.payload == msg.payload link.add_callback(SBP_MSG_PRINT_DEP, tester) t0 = time.time() sleep = 0.1 while True: if time.time() - t0 < sleep: break
def test_http_test_pass_retry(): assert is_enabled() msg = MsgPrintDep(text='abcd') get_responses = [ Response(body="first response", status=500, content_type="application/vnd.swiftnav.broker.v1+sbp2"), Response(body='second and last response', status=200, content_type="application/vnd.swiftnav.broker.v1+sbp2") ] post_responses = [ Response(body="", status=500, content_type="application/vnd.swiftnav.broker.v1+sbp2"), Response(body='', status=200, content_type="application/vnd.swiftnav.broker.v1+sbp2") ] register_uri(GET, BASE_STATION_URI, get_responses) register_uri(PUT, BASE_STATION_URI, post_responses) with HTTPDriver(device_uid="Swift22", url=BASE_STATION_URI) as driver: with pytest.raises(ValueError): driver.read(size=255) assert driver.connect_read() assert driver.read(size=255)
def test_http_test_pass_streaming(): assert is_enabled() msgs = [ MsgPrintDep(text='foo'), MsgPrintDep(text='bar'), MsgPrintDep(text='baz') ] register_uri(GET, BASE_STATION_URI, mock_streaming_msgs([m.to_binary() for m in msgs]), content_type="application/vnd.swiftnav.broker.v1+sbp2", streaming=True) register_uri(PUT, BASE_STATION_URI, body='', content_type="application/vnd.swiftnav.broker.v1+sbp2", streaming=True) with HTTPDriver(device_uid="Swift22", url=BASE_STATION_URI) as driver: assert driver.connect_read() assert driver.read_ok assert driver.read(size=255) == ''.join([m.to_binary() for m in msgs]) assert driver.read(size=255) == '' assert not driver.read_close() assert driver.read_response is None assert not driver.read_ok with pytest.raises(ValueError): driver.read(size=255)
def main(args): """ Get configuration, get driver, get logger, and build handler and start it. """ timeout = args.timeout log_filename = args.logfilename log_dirname = args.log_dirname if not log_filename: log_filename = logfilename() if log_dirname: log_filename = os.path.join(log_dirname, log_filename) # State for handling a networked base stations. channel = args.channel_id serial_id = int(args.serial_id) if args.serial_id is not None else None base = args.base use_broker = args.broker # Driver with context driver = get_base_args_driver(args) with Handler(Framer(driver.read, driver.write, args.verbose)) as link: # Logger with context with get_logger(args.log, log_filename, args.expand_json) as logger: link.add_callback(printer, SBP_MSG_PRINT_DEP) link.add_callback(log_printer, SBP_MSG_LOG) Forwarder(link, logger).start() if use_broker and base and serial_id: device_id = get_uuid(channel, serial_id) with HTTPDriver(str(device_id), base) as http: with Handler(Framer(http.read, http.write, args.verbose)) as slink: Forwarder(slink, swriter(link)).start() run(args, link) else: run(args, link)
def main(args): """ Get configuration, get driver, get logger, and build handler and start it. """ port = args.port baud = args.baud timeout = args.timeout log_filename = args.log_filename append_log_filename = args.append_log_filename tags = args.tags # State for handling a networked base stations. channel = args.channel_id serial_id = int(args.serial_id) if args.serial_id is not None else None base = args.base use_broker = args.broker # Driver with context with get_driver(args.ftdi, port, baud, args.file) as driver: # Handler with context with Handler(Framer(driver.read, driver.write, args.verbose)) as link: # Logger with context with get_logger(args.log, log_filename) as logger: with get_append_logger(append_log_filename, tags) as append_logger: link.add_callback(printer, SBP_MSG_PRINT_DEP) link.add_callback(log_printer, SBP_MSG_LOG) Forwarder(link, logger).start() Forwarder(link, append_logger).start() if use_broker and base and serial_id: device_id = get_uuid(channel, serial_id) with HTTPDriver(str(device_id), base) as http: with Handler(Framer(http.read, http.write, args.verbose)) as slink: Forwarder(slink, swriter(link)).start() run(args, link) else: run(args, link)
def test_http_test_pass(): assert is_enabled() msg = MsgPrintDep(text='abcd') register_uri(GET, BASE_STATION_URI, msg.to_binary(), content_type="application/vnd.swiftnav.broker.v1+sbp") with HTTPDriver(device_uid="Swift22", url=BASE_STATION_URI) as driver: assert driver.read(size=255) == msg.to_binary()
def test_http_test_fail(): assert is_enabled() msg = MsgPrintDep(text='abcd') register_uri(GET, BASE_STATION_URI, msg.to_binary(), content_type="application/vnd.swiftnav.broker.v1+sbp", status=400) with HTTPDriver(device_uid="Swift22", url=BASE_STATION_URI) as driver: with pytest.raises(RuntimeError) as exc_info: driver.read(size=255) assert exc_info.value.message.startswith("Request failed! With code 400:")
def main(args): """ Get configuration, get driver, get logger, and build handler and start it. """ port = args.port baud = args.baud timeout = args.timeout log_filename = args.logfilename log_dirname = args.log_dirname if not log_filename: log_filename = logfilename() if log_dirname: log_filename = os.path.join(log_dirname, log_filename) append_log_filename = args.append_log_filename tags = args.tags # State for handling a networked base stations. channel = args.channel_id serial_id = int(args.serial_id) if args.serial_id is not None else None base = args.base use_broker = args.broker # Driver with context if args.tcp: try: host, port = port.split(':') driver = TCPDriver(host, int(port)) except: # noqa raise Exception('Invalid host and/or port') else: driver = get_driver(args.ftdi, port, baud, args.file, rtscts=args.rtscts) # Handler with context with Handler(Framer(driver.read, driver.write, args.verbose)) as link: # Logger with context with get_logger(args.log, log_filename, args.expand_json) as logger: with get_append_logger(append_log_filename, tags) as append_logger: link.add_callback(printer, SBP_MSG_PRINT_DEP) link.add_callback(log_printer, SBP_MSG_LOG) Forwarder(link, logger).start() Forwarder(link, append_logger).start() if use_broker and base and serial_id: device_id = get_uuid(channel, serial_id) with HTTPDriver(str(device_id), base) as http: with Handler( Framer(http.read, http.write, args.verbose)) as slink: Forwarder(slink, swriter(link)).start() run(args, link) else: run(args, link)
def test_http_test_pass_streaming(): assert is_enabled() msgs = [ MsgPrintDep(text='foo'), MsgPrintDep(text='bar'), MsgPrintDep(text='baz') ] register_uri(GET, BASE_STATION_URI, mock_streaming_msgs([m.to_binary() for m in msgs]), content_type="application/vnd.swiftnav.broker.v1+sbp", streaming=True) with HTTPDriver(device_uid="Swift22", url=BASE_STATION_URI) as driver: assert driver.read(size=255) == ''.join([m.to_binary() for m in msgs])
def test_http_test_fail(): assert is_enabled() msg = MsgPrintDep(text='abcd') register_uri(GET, BASE_STATION_URI, msg.to_binary(), content_type="application/vnd.swiftnav.broker.v1+sbp2", status=400) register_uri(PUT, BASE_STATION_URI, '', content_type="application/vnd.swiftnav.broker.v1+sbp2", status=400) with HTTPDriver(device_uid="Swift22", url=BASE_STATION_URI) as driver: assert not driver.connect_read() assert not driver.read_ok with pytest.raises(IOError): driver.read(size=255)
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()
traceback.print_exc() # Make sure that SIGINT (i.e. Ctrl-C from command line) actually stops the # application event loop (otherwise Qt swallows KeyboardInterrupt exceptions) signal.signal(signal.SIGINT, signal.SIG_DFL) # Passing only a base station argument, we just want to display the # base station data in the console. Otherwise, continue, assuming a # rover connected to the serial port. if port is None and base is None: sys.stderr.write("ERROR: No data source specified!") sys.exit(1) if port is None and base and use_broker: device_id = get_uuid(channel, serial_id) with HTTPDriver(str(device_id), base) as http_driver: with sbpc.Handler(sbpc.Framer(http_driver.read, None, args.verbose)) as link: if os.path.isdir(log_filename): log_filename = os.path.join(log_filename, s.LOG_FILENAME) with s.get_logger(args.log, log_filename) as logger: link.add_callback(logger) log_filter = DEFAULT_LOG_LEVEL_FILTER if args.initloglevel[0]: log_filter = args.initloglevel[0] SwiftConsole(link, args.update, log_filter, True).configure_traits() try: os._exit(0) except: pass
def connect(self, link, read_config): """Retry read connections. Intended to be called when thread started Only shared resource here is the self.link Parameters ---------- link : SbpHandler read_config : SkylarkConsoleConnectConfig object Returns ---------- ret : int 0 if exited normally by thread stopping -1 if unable to connect as base station -2 if unable to connect as rover -3 if we lost our net connection to skylark (we restart in this case unless stopped) """ assert isinstance(read_config, SkylarkConsoleConnectConfig) self._connect_time = time.time() if self.verbose: print(("SkylarkWatchdogThread connection attempted at time {0} with parameters {1}".format( self.get_connect_time(), read_config))) i = 0 repeats = 5 http = HTTPDriver(device_uid=read_config.base_uuid, url=read_config.skylark_url) if not http.connect_write(link, read_config.whitelist, pragma=read_config.base_pragma): msg = ("\nUnable to connect to Skylark!\n\n" + "Please check that you have a network connection.") self._prompt_networking_error(msg) http.close() self.stop() return -1 # unable to connect as base time.sleep(1) # If we get here, we were able to connect as a base print("Attempting to read observation from Skylark...") while (not self.stopped() and http and not http.connect_read(device_uid=read_config.rover_uuid, pragma=read_config.rover_pragma)): 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) http.close() self.stop() return -2 # Unable to connect as rover # If we get here, we were able to connect as rover print("Connected as a rover!") with Handler(Framer(http.read, http.write)) as net_link: fwd = Forwarder(net_link, swriter(link)) if self.verbose: print("Starting forwarder") fwd.start() # now we sleep until we stop the thread or our http handler dies while not self.stopped() and net_link.is_alive(): time.sleep(0.1) # when we leave this loop, we are no longer connected to skylark so the fwd should be stopped if self.verbose: print("Stopping forwarder") fwd.stop() if self.verbose: print("Stopping HTTPDriver") http.close() # now manage the return code if self.stopped(): return 0 # If we stop from the event, it it intended and we return 0 else: return -3 # Lost connection
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()
def connect(self, link, read_config): """Retry read connections. Intended to be called when thread started Only shared resource here is the self.link Parameters ---------- link : SbpHandler read_config : HttpConsoleConnectConfig object Returns ---------- ret : int 0 if exited normally by thread stopping -1 if unable to connect as base station -2 if unable to connect as rover -3 if we lost our network connection (we restart in this case unless stopped) """ assert isinstance(read_config, HttpConsoleConnectConfig) self._connect_time = time.time() if self.verbose: print( "HttpWatchdogThread connection attempted at time {0} with parameters {1}". format(self.get_connect_time(), read_config)) i = 0 repeats = 5 http = HTTPDriver( device_uid=read_config.base_uuid, url=read_config.url) if not http.connect_write( link, read_config.whitelist, pragma=read_config.base_pragma): msg = ("\nUnable to connect!\n\n" + "Please check that you have a network connection.") self._prompt_networking_error(msg) http.close() self.stop() return -1 # unable to connect as base time.sleep(1) # If we get here, we were able to connect as a base print("Attempting to read observations ...") while (not self.stopped() and http and not http.connect_read( device_uid=read_config.rover_uuid, pragma=read_config.rover_pragma)): time.sleep(0.1) i += 1 if i >= repeats: msg = ("\nUnable to receive observations!\n\n" "Please check that:\n" " - you have a network connection\n" " - your Piksi has a single-point position\n" " - your Piksi has sent its settings to the console") self._prompt_networking_error(msg) http.close() self.stop() return -2 # Unable to connect as rover # If we get here, we were able to connect as rover print("Connected as a rover!") with Handler(Framer(http.read, http.write)) as net_link: fwd = Forwarder(net_link, swriter(link)) if self.verbose: print("Starting forwarder") fwd.start() # now we sleep until we stop the thread or our http handler dies while not self.stopped() and net_link.is_alive(): time.sleep(0.1) # when we leave this loop, we are no longer connected so the fwd should be stopped if self.verbose: print("Stopping forwarder") fwd.stop() if self.verbose: print("Stopping HTTPDriver") http.close() # now manage the return code if self.stopped(): return 0 # If we stop from the event, it it intended and we return 0 else: return -3 # Lost connection