def _build_connection(self, config): """ Constructs and returns a Connection object according to the given configuration. The object returned here is a VadcpClient instance. @param config configuration dict @retval a VadcpClient instance @throws InstrumentParameterException Invalid configuration. """ log.info('_build_connection: config=%s' % config) c4 = config['four_beam'] outfilename = 'vadcp_output_%s_%s.txt' % (c4.host, c4.port) u4_outfile = file(outfilename, 'w') c5 = config['fifth_beam'] outfilename = 'vadcp_output_%s_%s.txt' % (c5.host, c5.port) u5_outfile = file(outfilename, 'w') log.info("setting VadcpClient with config: %s" % config) try: client = VadcpClient(config, u4_outfile, u5_outfile) except (TypeError, KeyError): raise InstrumentParameterException('Invalid comms config dict.' ' config=%s' % config) # set data_listener to the client so we can notify corresponding # DriverAsyncEvent.SAMPLE events: def _data_listener(sample): log.info("_data_listener: sample = %s" % str(sample)) self._driver_event(DriverAsyncEvent.SAMPLE, val=sample) client.set_data_listener(_data_listener) return client
def tearDownClass(cls): try: if cls._client: log.info("ending UnitClient object") cls._client.end() finally: super(Test, cls).tearDownClass()
def tearDownClass(cls): try: if cls._client: log.info("ending VadcpClient object") cls._client.end() finally: super(Test, cls).tearDownClass()
def test_execute_run_all_tests(self): self._prepare_and_connect() result = self.driver.execute_run_all_tests(timeout=self._timeout) log.info("execute_run_all_tests result=%s" % prefix(result)) self._disconnect()
def test_execute_get_latest_sample(self): self._prepare_and_connect() result = self.driver.execute_get_latest_sample(timeout=self._timeout) log.info("get_latest_sample result = %s" % str(result)) self._disconnect()
def build_receiver(cls, sock, bufsize=4096, ooi_digi=False, data_listener=None, outfile=None, prefix_state=True): """ Creates a returns a receiver object that handles all received responses from the connection, keeping relevant information and a state. @param sock To read in from the instrument, sock.recv(bufsize) @param bufsize To read in from the instrument, sock.recv(bufsize) @param ooi_digi True to indicate the connection is with an OOI Digi; False to indicate the connection is with an actual ADCP unit. By default, False. @param data_listener @param outfile @param prefix_state """ receiver = _Receiver(sock, bufsize, ooi_digi, data_listener, outfile, prefix_state) if cls._use_greenlet: from gevent import Greenlet runnable = Greenlet(receiver.run) log.info("Created Greenlet-based _Receiver") else: from threading import Thread runnable = Thread(target=receiver.run) runnable.setDaemon(True) log.info("Created Thread-based _Receiver") receiver._thr = runnable return receiver
def __init__(self, device_address, device_port): """ Setup test cases. """ driver_module = "mi.instrument.uw.res_probe.ooicore.trhph_driver" driver_class = "TrhphInstrumentDriver" self._support = DriverIntegrationTestSupport(driver_module, driver_class, device_address, device_port) # Create and start the port agent. mi_logger.info("starting port agent") self.comms_config = {"addr": "localhost", "port": self._support.start_pagent()} # Create and start the driver. mi_logger.info("starting driver client") ##<update-july-2012>: ## start_driver and _dvr_client no longer defined in ## DriverIntegrationTestSupport # self._support.start_driver() # self._dvr_client = self._support._dvr_client dvr_config = { "comms_config": self.comms_config, "dvr_mod": driver_module, "dvr_cls": driver_class, "workdir": "/tmp/", "process_type": ("ZMQPyClassDriverLauncher",), } self._start_driver(dvr_config)
def run(self): """ Runs the receiver. """ # set a timeout to the socket so we can regularly check that we are # still to be active (see self._recv()); if self._sock.gettimeout() is None: self._sock.settimeout(0.4) log.info("_Receiver running") self._active = True # set up pipeline if self._ooi_digi: # no need to parse for timestamps or PD0 ensembles: pipeline = self.sink() else: pipeline = timestamp_filter(pd0_filter(self.sink())) # and read in and push received data into the pipeline: while self._active: recv = self._recv() if recv is not None: pipeline.send(({}, recv)) pipeline.close() self._end_outfile() log.info("_Receiver ended.")
def setUpClass(cls): """ Sets up _conn_config, _timeout, according to environment variables. """ cls._skip_reason = None # # cls._conn_config # cls._conn_config = None vadcp = os.getenv('VADCP') if vadcp: filename = vadcp log.info("loading connection params from '%s'" % filename) try: f = open(filename) yml = yaml.load(f) f.close() def create_unit_conn_config(yml): return AdcpUnitConnConfig(yml.get('host'), yml.get('port'), yml.get('ooi_digi_host'), yml.get('ooi_digi_port')) cls._conn_config = { 'four_beam': create_unit_conn_config(yml['four_beam']), 'fifth_beam': create_unit_conn_config(yml['fifth_beam']) } except Exception, e: cls._skip_reason = "Problem with connection config file: '%s': %s" % ( filename, str(e)) log.warn(cls._skip_reason)
def user_loop(client): """ Sends lines received from stdin to the socket. EOF and "q" break the loop. """ polled = False while True: cmd = sys.stdin.readline() if not cmd: break cmd = cmd.strip() if cmd == "q": break elif re.match(r"CP\s*(0|1)", cmd, re.IGNORECASE): cmd = cmd.upper() polled = cmd.endswith('1') client.send(cmd) log.info("polled set to: %s" % polled) elif cmd == "break": client.send_break() elif polled and cmd.upper() in ['!', '+', '-', 'D', 'E', 'T']: # See Table 10: Polled Mode Commands in "Workhorse Commands # an Output Data Format" doc. # I've noted (on both units) that only '!' and '+' are # actually handled, that is, with no echo and apparently # triggering the documented behavior (certainly for the '!' # break reset one); the others are echoed and probably not # causing the corresponding behavior. cmd = cmd.upper() client._send(cmd, info="sending polled mode cmd='%s'" % cmd) else: client.send(cmd)
def setUpClass(cls): super(Test, cls).setUpClass() if cls._skip_reason: return ReceiverBuilder.use_greenlets() cls._samples_recd = 0 c4 = cls._conn_config['four_beam'] outfilename = 'vadcp_output_%s_%s.txt' % (c4.host, c4.port) u4_outfile = file(outfilename, 'w') c5 = cls._conn_config['fifth_beam'] outfilename = 'vadcp_output_%s_%s.txt' % (c5.host, c5.port) u5_outfile = file(outfilename, 'w') cls._client = VadcpClient(cls._conn_config, u4_outfile, u5_outfile) cls._client.set_generic_timeout(cls._timeout) log.info("connecting") cls._client.set_data_listener(cls._data_listener) cls._client.connect() log.info("sending break and waiting for prompt") cls._client.send_break()
def __init__(self, device_address, device_port): """ Setup test cases. """ driver_module = 'mi.instrument.uw.res_probe.ooicore.trhph_driver' driver_class = 'TrhphInstrumentDriver' self._support = DriverIntegrationTestSupport(driver_module, driver_class, device_address, device_port) # Create and start the port agent. mi_logger.info('starting port agent') self.comms_config = { 'addr': 'localhost', 'port': self._support.start_pagent()} # Create and start the driver. mi_logger.info('starting driver client') ##<update-july-2012>: ## start_driver and _dvr_client no longer defined in ## DriverIntegrationTestSupport # self._support.start_driver() # self._dvr_client = self._support._dvr_client dvr_config = { 'comms_config': self.comms_config, 'dvr_mod': driver_module, 'dvr_cls': driver_class, 'workdir' : '/tmp/', 'process_type': ('ZMQPyClassDriverLauncher',) } self._start_driver(dvr_config)
def _connect_ooi_digi(self): """ Establishes the connection to the OOI digi. The connection is attempted a number of times. NOTE: The connection has sporadically failed, which have been fixed by rebooting the unit through the web interface (which is http://10.180.80.178/html/reboot.htm for the 4-beam unit). """ host = self._conn_config.ooi_digi_host port = self._conn_config.ooi_digi_port sock = connect_socket(host, port, timeout=self._generic_timeout) if 'localhost' == host: outfilename = 'vadcp_ooi_digi_output.txt' else: outfilename = 'vadcp_output_%s_%s.txt' % (host, port) outfile = open(outfilename, 'a') log.info("creating OOI Digi _Receiver") rt = ReceiverBuilder.build_receiver(sock, ooi_digi=True, outfile=outfile) log.info("starting OOI Digi _Receiver") rt.start() return (sock, rt, host, port)
def _set_state(self, state): if self._state != state: log.info("{{TRANSITION: %s => %s %r}}" % (self._state, state, self._last_line)) if self._last_line: log.debug("LINES=\n\t|%s" % "\n\t|".join(self._lines)) self._state = state
def use_default(cls): """ This method instructs the builder to use Thread-based receivers, which is the default, """ if cls._use_greenlet: cls._use_greenlet = False log.info("ReceiverBuilder configured to use threads")
def setUp(self): """ """ if self._skip_reason: self.skipTest(self._skip_reason) log.info("== VADCP _conn_config: %s" % self._conn_config)
def _connect(self): self.driver.connect() state = self.driver.get_resource_state() log.info("connect -> %s" % str(state)) # self.assertEqual(DriverState.CONNECTED, state) if DriverState.CONNECTED == state: pass # OK else: self.assertTrue(state.startswith('PROTOCOL_STATE'))
def use_greenlets(cls): """ The builder creates Thread-based receivers by default. This method instructs the builder to use Greenlet-based receivers in subsequent calls to build_receiver. """ if not cls._use_greenlet: cls._use_greenlet = True log.info("ReceiverBuilder configured to use greenlets")
def test_get_metadata(self): sections = None # None => all sections result = self._client.get_metadata(sections) self.assertTrue(isinstance(result, dict)) s = "" for name, text in result.items(): self.assertTrue(name in md_section_names) s += "**%s:%s\n\n" % (name, prefix(text, "\n ")) log.info("METADATA result=%s" % prefix(s))
def test_get_metadata(self): sections = None # None => all sections result = self._client.get_metadata(sections) self.assertTrue(isinstance(result, dict)) s = '' for name, text in result.items(): self.assertTrue(name in md_section_names) s += "**%s:%s\n\n" % (name, prefix(text, "\n ")) log.info("METADATA result=%s" % prefix(s))
def _send(self, s, info=None): """ Sends a string. Returns the number of bytes written. @param s the string to send @param info string for logging purposes """ c = self._sock.send(s) if log.isEnabledFor(logging.INFO): info_str = (' (%s)' % info) if info else '' log.info("_send:%s%s" % (repr(s), info_str)) return c
def test_start_and_stop_autosample(self): self._prepare_and_connect() result = self.driver.execute_start_autosample(timeout=self._timeout) log.info("execute_start_autosample result=%s" % prefix(result)) time.sleep(6) result = self.driver.execute_stop_autosample(timeout=self._timeout) log.info("execute_stop_autosample result=%s" % prefix(result)) self._disconnect()
def _get_prompt(self, attempts=5): """ Send linefeeds until getting prompt """ # timeout for each attempt timeout = 1 last_exc = None for a in xrange(attempts): log.info("_get_prompt: attempt=%d" % (a + 1)) try: r = self.send_and_expect_prompt("", timeout) return r # got it except TimeoutException, e: last_exc = e
def test_execute_get_metadata(self): self._prepare_and_connect() sections = None result = self.driver.execute_get_metadata(sections, timeout=self._timeout) self.assertTrue(isinstance(result, dict)) s = '' for unit, unit_result in result.items(): s += "==UNIT: %s==\n\n" % unit for name, text in unit_result.items(): self.assertTrue(name in md_section_names) s += "**%s:%s\n\n" % (name, prefix(text, "\n ")) log.info("METADATA result=%s" % prefix(s)) self._disconnect()
def end(self): """ Ends the client. """ if self._sock is None: log.warn("end() called again") return log.info("closing connection") try: if self._rt: self._rt.end() # self._sock.shutdown(socket.SHUT_RDWR) self._sock.close() # log.info("socket shutdown and closed") log.info("socket closed") finally: self._sock = None
def send_break(self, duration=1000, attempts=3, timeout=None): """ Issues a "break <duration>" command to the OOI digi. @param duration Duration for the break command (by default 1000) @param attempts Max number of attempts, 3 by default. @param timeout @retval True iff the command has had effect. """ timeout = timeout or self._generic_timeout # TODO the expectation below should be getting the corresponding # response on the regular raw port. sock, rt, host, port = self._connect_ooi_digi() ok = False try: for a in xrange(attempts): time.sleep(1) rt.reset_internal_info() log.info("Sending break (attempt=%d)" % (a + 1)) sock.send("break %s%s" % (duration, EOLN)) time.sleep(2) response = "\n".join(rt.lines) ok = response.find("Sending Serial Break") >= 0 if ok: break finally: log.info("Got expected response from OOI Digi: %s" % ok) log.info("ending OOI Digi receiver") rt.end() time.sleep(2) log.info("closing socket to OOI Digi on: %s, %s" % (host, port)) sock.close() log.info("socket to OOI Digi closed") return ok
def __init__(self, conn_config, outfile=None, prefix_state=True): """ Creates a UnitClient instance. @param conn_config AdcpUnitConnConfig @param outfile @param prefix_state """ self._conn_config = conn_config self._outfile = outfile self._prefix_state = prefix_state self._sock = None self._rt = None # receiver thread """sleep time used just before sending data""" self._delay_before_send = 0.2 """generic timeout for various operations""" self._generic_timeout = DEFAULT_GENERIC_TIMEOUT log.info("UnitClient created.")
def __init__(self, conn_config, b4_outfile=None, b5_outfile=None): """ Creates a VadcpClient instance. @param conn_config connection configurations for the two units @param b4_outfile @param b5_outfile """ self._u4 = UnitClient(conn_config['four_beam'], outfile=b4_outfile) self._u5 = UnitClient(conn_config['fifth_beam'], outfile=b5_outfile) # sleep time used just before sending data self._delay_before_send = 0.2 # generic timeout for various operations self._generic_timeout = DEFAULT_GENERIC_TIMEOUT log.info("VADCP client object created.")
def configure(self, *args, **kwargs): """ Configure the driver for communications with the device via port agent / logger (valid but unconnected connection object). @param config comms config dict. @raises InstrumentStateException if command not allowed in current state @throws InstrumentParameterException if missing comms or invalid config dict. """ if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) self._assert_state(DriverState.UNCONFIGURED) config = kwargs.get('config', None) if config is None: # raise InstrumentParameterException(msg="'config' parameter required") config = args[0] c4 = config['four_beam'] outfilename = 'vadcp_output_%s_%s.txt' % (c4.host, c4.port) u4_outfile = file(outfilename, 'w') c5 = config['fifth_beam'] outfilename = 'vadcp_output_%s_%s.txt' % (c5.host, c5.port) u5_outfile = file(outfilename, 'w') # Verify dict and construct connection client. log.info("setting VadcpClient with config: %s" % config) try: self._client = VadcpClient(config, u4_outfile, u5_outfile) except (TypeError, KeyError): raise InstrumentParameterException('Invalid comms config dict.' ' config=%s' % config) self._driver_event(DriverAsyncEvent.STATE_CHANGE) self._state = DriverState.DISCONNECTED
def connect(self): """ Establishes the connection and starts the receiving thread. @throws socket.error The socket.error that was raised during the last attempt to connect the socket. """ assert self._sock is None host = self._conn_config.host port = self._conn_config.port self._sock = connect_socket(host, port) log.info("creating _Receiver") self._rt = ReceiverBuilder.build_receiver(self._sock, ooi_digi=False, outfile=self._outfile, data_listener=self._data_listener, prefix_state=self._prefix_state) log.info("starting _Receiver") self._rt.start()
def __init__(self, device_address, device_port): """ Setup test cases. """ driver_module = 'mi.instrument.uw.res_probe.ooicore.trhph_driver' driver_class = 'TrhphInstrumentDriver' self._support = DriverIntegrationTestSupport(driver_module, driver_class, device_address, device_port) # Create and start the port agent. mi_logger.info('starting port agent') self.comms_config = {'addr': 'localhost'} self.comms_config['port'] = self._support.start_pagent() # Create and start the driver. mi_logger.info('starting driver client') self._support.start_driver() self._dvr_client = self._support._dvr_client
def connect(self): """ Establishes the connection and starts the receiving thread. @throws socket.error The socket.error that was raised during the last attempt to connect the socket. """ assert self._sock is None host = self._conn_config.host port = self._conn_config.port self._sock = connect_socket(host, port) log.info("creating _Receiver") self._rt = ReceiverBuilder.build_receiver( self._sock, ooi_digi=False, outfile=self._outfile, data_listener=self._data_listener, prefix_state=self._prefix_state) log.info("starting _Receiver") self._rt.start()
def __init__(self, device_address, device_port): """ Setup test cases. """ driver_module = 'mi.instrument.uw.res_probe.ooicore.trhph_driver' driver_class = 'TrhphInstrumentDriver' self._support = DriverIntegrationTestSupport(driver_module, driver_class, device_address, device_port) # Create and start the port agent. mi_logger.info('starting port agent') self.comms_config = { 'addr': 'localhost', 'port': self._support.start_pagent() } # Create and start the driver. mi_logger.info('starting driver client') ##<update-july-2012>: ## start_driver and _dvr_client no longer defined in ## DriverIntegrationTestSupport # self._support.start_driver() # self._dvr_client = self._support._dvr_client dvr_config = { 'comms_config': self.comms_config, 'dvr_mod': driver_module, 'dvr_cls': driver_class, 'workdir': '/tmp/', 'process_type': ('ZMQPyClassDriverLauncher', ) } self._start_driver(dvr_config)
def connect_socket(host, port, max_attempts=3, time_between_attempts=10, timeout=None): """ Establishes a socket connection, which is attempted a number of times. @param host @param port @param max_attempts Maximum number of socket connection attempts (3 by default). @param time_between_attempts Time in seconds between attempts (10 by default). @param timeout timeout in secs for each connect attempt (None by default) @retval open socket @throws socket.error The socket.error that was raised during the last attempt. """ last_error = None attempt = 0 sock = None while sock is None and attempt < max_attempts: attempt += 1 log.info("Trying to connect to %s:%s (attempt=%d)" % (host, port, attempt)) try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if timeout is not None: s.settimeout(timeout) log.info("socket object created. Connecting...") s.connect((host, port)) sock = s except socket.error, e: log.info("Socket error while trying to connect: %s" % str(e)) last_error = e if attempt < max_attempts: log.info("Re-attempting in %s secs ..." % str(time_between_attempts)) time.sleep(time_between_attempts)
def test_start_and_stop_autosample(self): Test._samples_recd = 0 if State.COLLECTING_DATA != self._client.get_current_state(): result = self._client.start_autosample() log.info("start_autosample result=%s" % result) self.assertEqual(State.COLLECTING_DATA, self._client.get_current_state()) time.sleep(6) log.info("ensembles_recd = %s" % Test._samples_recd) result = self._client.stop_autosample() log.info("stop_autosample result=%s" % result) self.assertEqual(State.PROMPT, self._client.get_current_state())
def __init__(self, conn_config): """ Setup test cases. """ driver_module = 'mi.instrument.teledyne.workhorse_adcp_5_beam_600khz.ooicore.driver' driver_class = 'VadcpDriver' u4_conn_config = conn_config['four_beam'] device_address = u4_conn_config.host device_port = u4_conn_config.port # TODO set up port agent for the OOI Digi connection as well. self._support = DriverIntegrationTestSupport(driver_module, driver_class, device_address, device_port) # Create and start the port agent, which runs on localhost log.info('starting port agent') pagent_port = self._support.start_pagent() # so, we now connect to the 4-beam via the port agent: # Note that only the raw connection is adjusted self.comms_config = { 'four_beam': AdcpUnitConnConfig('localhost', pagent_port, u4_conn_config.ooi_digi_host, u4_conn_config.ooi_digi_port), 'fifth_beam': conn_config['fifth_beam'] } log.info("comms_config: %s" % self.comms_config) # Create and start the driver. log.info('starting driver client') self._support.start_driver() self._dvr_client = self._support._dvr_client