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 execute_stop_autosample(self, *args, **kwargs): if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) self._assert_state(DriverState.CONNECTED) timeout = kwargs.get('timeout', self._timeout) try: result = self._client.stop_autosample(timeout=timeout) return result except TimeoutException, e: raise InstrumentTimeoutException(msg=str(e))
def execute_get_metadata(self, *args, **kwargs): if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) self._assert_state(DriverState.CONNECTED) timeout = kwargs.get('timeout', self._timeout) sections = kwargs.get('sections', None) try: result = self._client.get_metadata(sections, timeout) return result except TimeoutException, e: raise InstrumentTimeoutException(msg=str(e))
def _handler_command_run_all_tests(self, *args, **kwargs): """ """ if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) next_state = self._protocol_fsm.get_current_state() result = None timeout = kwargs.get('timeout', self._timeout) try: result = self._connection.run_all_tests(timeout) except TimeoutException, e: raise InstrumentTimeoutException(msg=str(e))
def disconnect(self, *args, **kwargs): """ Disconnect from device via port agent / logger. @raises InstrumentStateException if command not allowed in current state """ if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) self._assert_state(DriverState.CONNECTED) self._client.end() self._driver_event(DriverAsyncEvent.STATE_CHANGE) self._state = DriverState.DISCONNECTED
def _handler_command_autosample(self, *args, **kwargs): """ """ if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) next_state = None result = None timeout = kwargs.get('timeout', self._timeout) try: result = self._connection.start_autosample(timeout=timeout) next_state = ProtocolState.AUTOSAMPLE_MODE except TimeoutException, e: raise InstrumentTimeoutException(msg=str(e))
def _handler_autosample_stop(self, *args, **kwargs): """ """ if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) next_state = None result = None duration = int(kwargs.get('duration', 1000)) try: result = self._connection.send_break(duration) next_state = ProtocolState.COMMAND_MODE except TimeoutException, e: raise InstrumentTimeoutException(msg=str(e))
def _recv(self): """ Main read method. Reads from the socket, updates the time of last received buffer, updates the outfile if any, and return the buffer. """ log.debug("reading") recv = None while self._active and recv is None: try: recv = self._sock.recv(self._bufsize) except socket.timeout, e: # ok, this is our regular check for active continue except socket.error, e: log.debug("socket.error: %s" % e) self._active = False return None
def connect(self, *args, **kwargs): """ Establish communications with the device via port agent / logger (connected connection object). @raises InstrumentStateException if command not allowed in current state @throws InstrumentConnectionException if the connection failed. """ if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) self._assert_state(DriverState.DISCONNECTED) self._client.set_data_listener(self._data_listener) self._client.connect() self._driver_event(DriverAsyncEvent.STATE_CHANGE) self._state = DriverState.CONNECTED
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 initialize(self, *args, **kwargs): """ Initialize driver connection, bringing communications parameters into unconfigured state (no connection object). @raises InstrumentStateException if command not allowed in current state """ if log.isEnabledFor(logging.DEBUG): log.debug("args=%s kwargs=%s" % (str(args), str(kwargs))) if self._state == DriverState.UNCONFIGURED: assert self._client is None return if self._client is not None: try: self._client.end() finally: self._client = None self._driver_event(DriverAsyncEvent.STATE_CHANGE) self._state = DriverState.UNCONFIGURED
def pd0_filter(receiver): """ A consumer generator that handles and filters out incoming PD0 ensembles, if any. It expects to be sent tuples of the form (xelems, buffer) where: - xelems is a dict of any extracted elements, never None. - buffer is a binary string to be analyzed (could be None). There are two cases for sending data to the receiver: Upon extracting a PD0 ensemble from the stream, this filter creates a PD0DataStructure instance, pd0, and calls receiver.sends( (xelems.update({'pd0', pd0}), None) ). For any unhandled bytes in the stream, this filter calls receiver.sends( (xelems.update({'pd0', None}), send_buffer) ) where send_buffer is a buffer of unrecognized bytes. """ data = "" # never None # the length of the current ensemble. Initialized with a # small number (but enough to extract the actual len): ensemble_len = MIN_LENGTH_TRY_ENSEMBLE while True: xelems, buffer = (yield) # for rcv in buffer: while buffer: idx = buffer.find("\x7f") if idx < 0: if len(data) == 0: xelems["pd0"] = None receiver.send((xelems, buffer)) break # ie., go receive more. elif idx > 0: if len(data) == 0: xelems["pd0"] = None receiver.send((xelems, buffer[0:idx])) buffer = buffer[idx:] rcv = buffer[0] buffer = buffer[1:] if rcv == "\x7f": if len(data) == 0: log.debug("RECEIVING DATA **") elif len(data) == 0: xelems["pd0"] = None receiver.send((xelems, rcv)) continue data += rcv if len(data) < ensemble_len: continue # if ensemble_len is our small number, it will still allow us # to "try" a structure and retrieve the actual ensemble length: # try: pd0 = PD0DataStructure(data) ensemble_len = pd0.getNumberOfBytesInEnsemble() except Exception: # # ok, we are not yet seeing the beginning of a structure, just # shift the data array a position and continue # receiving: # data = data[1:] continue if len(data) < ensemble_len: # # we don't yet have enough of the ensemble, just continue # receiving: # continue # we have our complete ensemble: ensemble = data[:ensemble_len] pd0 = PD0DataStructure(ensemble) xelems["pd0"] = pd0 receiver.send((xelems, None)) data = data[ensemble_len:] ensemble_len = MIN_LENGTH_TRY_ENSEMBLE
def _timestamp_received(self, ts): self._latest_ts = ts log.debug("{TIMESTAMP=%s}" % (ts))
def pd0_filter(receiver): """ A consumer generator that handles and filters out incoming PD0 ensembles, if any. It expects to be sent tuples of the form (xelems, buffer) where: - xelems is a dict of any extracted elements, never None. - buffer is a binary string to be analyzed (could be None). There are two cases for sending data to the receiver: Upon extracting a PD0 ensemble from the stream, this filter creates a PD0DataStructure instance, pd0, and calls receiver.sends( (xelems.update({'pd0', pd0}), None) ). For any unhandled bytes in the stream, this filter calls receiver.sends( (xelems.update({'pd0', None}), send_buffer) ) where send_buffer is a buffer of unrecognized bytes. """ data = '' # never None # the length of the current ensemble. Initialized with a # small number (but enough to extract the actual len): ensemble_len = MIN_LENGTH_TRY_ENSEMBLE while True: xelems, buffer = (yield) # for rcv in buffer: while buffer: idx = buffer.find('\x7f') if idx < 0: if len(data) == 0: xelems['pd0'] = None receiver.send((xelems, buffer)) break # ie., go receive more. elif idx > 0: if len(data) == 0: xelems['pd0'] = None receiver.send((xelems, buffer[0:idx])) buffer = buffer[idx:] rcv = buffer[0] buffer = buffer[1:] if rcv == '\x7f': if len(data) == 0: log.debug("RECEIVING DATA **") elif len(data) == 0: xelems['pd0'] = None receiver.send((xelems, rcv)) continue data += rcv if len(data) < ensemble_len: continue # if ensemble_len is our small number, it will still allow us # to "try" a structure and retrieve the actual ensemble length: # try: pd0 = PD0DataStructure(data) ensemble_len = pd0.getNumberOfBytesInEnsemble() except Exception: # # ok, we are not yet seeing the beginning of a structure, just # shift the data array a position and continue # receiving: # data = data[1:] continue if len(data) < ensemble_len: # # we don't yet have enough of the ensemble, just continue # receiving: # continue # we have our complete ensemble: ensemble = data[:ensemble_len] pd0 = PD0DataStructure(ensemble) xelems['pd0'] = pd0 receiver.send((xelems, None)) data = data[ensemble_len:] ensemble_len = MIN_LENGTH_TRY_ENSEMBLE
def _pd0_received(self, pd0): self._set_state(State.COLLECTING_DATA) self._latest_pd0 = pd0 log.debug("PD0=\n | %s" % (str(pd0).replace('\n', '\n | '))) if self._data_listener: self._data_listener(pd0)
def timestamp_filter(receiver): """ A consumer generator that filters out incoming timestamps, if any. It expects to be sent tuples of the form (xelems, buffer) where: - xelems is a dict of any extracted elements, never None. - buffer is a binary string to be analyzed (could be None). It calls: receiver.sends( (xelems.update({'latest_ts', latest_ts}), send_buffer) ) where latest_ts is the latest received and extracted timestamp (which could be None if not yet known or already reported in a previous send) and send_buffer is any unprocessed bytes in the incoming stream, which can be None if the upstream component hasn't provided any buffer to process. """ # latest received timestamp global latest_ts latest_ts = None def send(xelems, buffer): global latest_ts xelems['latest_ts'] = latest_ts latest_ts = None # only reported once receiver.send((xelems, buffer)) # we start by expecting the opening TS tag expecting_open_ts = True buffer = '' while True: xelems, rcv = (yield) if not rcv: # just forward to the receiver send(xelems, None) continue buffer = buffer + rcv log.debug("buffer_len = %s" % len(buffer)) need_more = False while len(buffer) > 0 and not need_more: if expecting_open_ts: mo = TS_OPEN_PATTERN.search(buffer) if mo: open_pos = mo.start() log.debug("TS found = %s at %s" % (mo.groups(), open_pos)) if open_pos > 0: log.debug("send %s bytes before start" % open_pos) send(xelems, buffer[0: open_pos]) # save this received timestamp for next send latest_ts = mo.group(1) buffer = buffer[mo.end():] expecting_open_ts = False else: (send_buf, buf) = _partial_match(buffer, TS_OPEN_STRING, TS_OPEN_SAFE_SIZE) if send_buf: send(xelems, send_buf) else: need_more = True buffer = buf else: # expecting closing TS tag close_pos = buffer.find(TS_CLOSE_STRING) if close_pos >= 0: if close_pos > 0: log.debug("send %s bytes before end" % close_pos) send(xelems, buffer[0: close_pos]) # just report closing tag found log.debug("closing tag at %s" % close_pos) buffer = buffer[close_pos + len(TS_CLOSE_STRING):] expecting_open_ts = True else: (send_buf, buf) = _partial_match(buffer, TS_CLOSE_STRING, len(TS_CLOSE_STRING)) if send_buf: send(xelems, send_buf) else: need_more = True buffer = buf
log.debug("reading") recv = None while self._active and recv is None: try: recv = self._sock.recv(self._bufsize) except socket.timeout, e: # ok, this is our regular check for active continue except socket.error, e: log.debug("socket.error: %s" % e) self._active = False return None if self._active and recv: self._recv_time = time.time() log.debug("read %s bytes" % len(recv)) self._update_outfile(recv) return recv else: return None 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 end(self): self._active = False