Example #1
0
    def _set_params(self, *args, **kwargs):
        """
        Issue commands to the instrument to set various parameters
        Also called when setting parameters during startup and direct access
        In the event an exception is generated dur
        @throws InstrumentParameterException if parameter does not exist or Maxrate is out of range
        @throws InstrumentCommandException if failed to set
        """

        params = args[0]

        self._verify_not_readonly(*args, **kwargs)
        old_config = self._param_dict.get_config()

        exception = None

        for key in params:
            if key not in self._param_dict._param_dict:
                exception = InstrumentParameterException("Bad parameter: %r" %
                                                         key)
                break
            val = self._param_dict.format(key, params[key])
            log.debug("KEY = %s VALUE = %s", str(key), str(val))
            if key == Parameter.MAX_RATE and float(
                    params[key]) not in VALID_MAXRATES:
                exception = InstrumentParameterException(
                    "Maxrate %s out of range" % val)
                break
            # Check for existence in dict (send only on change)
            if self._param_dict.get(
                    key) is None or val != self._param_dict.format(key):
                if not self._do_cmd_resp(Command.SET, key, val):
                    exception = InstrumentCommandException(
                        'Error setting: %s = %s' % (key, val))
                    break
                self._param_dict.set_value(key, params[key])

            time.sleep(0.5)

        # Get new param dict config. If it differs from the old config,
        # tell driver superclass to publish a config change event.
        new_config = self._param_dict.get_config()
        log.debug("new_config: %s == old_config: %s", new_config, old_config)
        if old_config != new_config:
            self._do_cmd_resp(Command.SAVE, expected_prompt=Prompt.COMMAND)
            log.debug("configuration has changed.  Send driver event")
            self._driver_event(DriverAsyncEvent.CONFIG_CHANGE)

        # Raise any exceptions encountered due to errors setting the parameter(s)
        if exception is not None:
            raise exception
Example #2
0
    def _send_command(self, command, *args, **kwargs):
        if not COMMAND_SEM.acquire(False):
            return 'BUSY'

        try:
            cmd_func = getattr(self.driver, command, None)

            if cmd_func and callable(cmd_func):
                reply = cmd_func(*args, **kwargs)
            else:
                raise InstrumentCommandException('Unknown driver command.')

            return reply

        finally:
            COMMAND_SEM.release()
    def cmd_driver(self, msg):
        """
        Process a command message against the driver. If the command
        exists as a driver attribute, call it passing supplied args and
        kwargs and returning the driver result. Special messages that are
        not forwarded to the driver are:
        'stop_driver_process' - signal to close messaging and terminate.
        'test_events' - populate event queue with test data.
        'process_echo' - echos the message back.
        If the command is not found in the driver, an echo message is
        replied to the client.
        @param msg A driver command message.
        @retval The driver command result.
        """
        cmd = msg.get('cmd', None)
        args = msg.get('args', None)
        kwargs = msg.get('kwargs', None)
        cmd_func = getattr(self.driver, cmd, None)
        log.debug("DriverProcess.cmd_driver(): cmd=%s, cmd_func=%s" %(cmd, cmd_func))
        if cmd == 'stop_driver_process':
            self.stop_messaging()
            return'stop_driver_process'
        elif cmd == 'test_events':
            events = kwargs['events']
            if type(events) != list:
                events = [events]
            for event in events:
                self.events.put(event)
            reply = 'test_events'
        elif cmd == 'process_echo':
            reply = 'ping from resource ppid:%s, resource:%s' % (str(self.ppid), str(self.driver))
        elif cmd_func:
            try:
                reply = cmd_func(*args, **kwargs)
            except Exception as e:
                reply = e
                if not isinstance(e, InstrumentException):
                    trace = traceback.format_exc()
                    log.critical("Python error, Trace follows: \n%s" %trace)

        else:
            reply = InstrumentCommandException('Unknown driver command.')

        return reply
Example #4
0
    def _do_cmd_resp(self, cmd, *args, **kwargs):
        """
        Perform a command-response on the device. Overridden: special "write delay" & command resending
        reliability improvements, no need for wakeup, default build command used for all commands
        @param cmd The command to execute.
        @param args positional arguments to pass to the build handler.
        @param expected_prompt kwarg offering a specific prompt to look for
        other than the ones in the protocol class itself.
        @param response_regex kwarg with a compiled regex for the response to
        match. Groups that match will be returned as a string.
        Cannot be supplied with expected_prompt. May be helpful for instruments that do not have a prompt.
        @retval resp_result The (possibly parsed) response result including the
        first instance of the prompt matched. If a regex was used, the prompt
        will be an empty string and the response will be the joined collection of matched groups.
        @raises InstrumentTimeoutException if the response did not occur in time.
        @raises InstrumentProtocolException if command could not be built or if response was not recognized.
        """
        timeout = kwargs.get('timeout', DEFAULT_CMD_TIMEOUT)
        expected_prompt = kwargs.get('expected_prompt', None)
        response_regex = kwargs.get('response_regex', None)

        if response_regex and not isinstance(response_regex, RE_PATTERN):
            raise InstrumentProtocolException('Response regex is not a compiled pattern!')

        if expected_prompt and response_regex:
            raise InstrumentProtocolException('Cannot supply both regex and expected prompt!')

        retry_count = 5
        retry_num = 0
        cmd_line = ""
        result = ""
        prompt = ""
        for retry_num in xrange(retry_count):
            # Clear line and prompt buffers for result.
            self._linebuf = ''
            self._promptbuf = ''

            cmd_line = self._do_cmd(cmd, *args, **kwargs)

            # Wait for the prompt, prepare result and return, timeout exception
            if response_regex:
                result_tuple = self._get_response(timeout, response_regex=response_regex,
                                                  expected_prompt=expected_prompt)
                result = "".join(result_tuple)
            else:
                (prompt, result) = self._get_response(timeout, expected_prompt=expected_prompt)

            # Confirm the entire command was sent, otherwise resend retry_count number of times
            if len(cmd_line) > 1 and \
                (expected_prompt is not None or
                (response_regex is not None))\
                    and not result.startswith(cmd_line):
                    # and cmd_line not in result:
                log.debug("_do_cmd_resp: Send command: %s failed %s attempt, result = %s.", cmd, retry_num, result)
                if retry_num >= retry_count:
                    raise InstrumentCommandException('_do_cmd_resp: Failed %s attempts sending command: %s' %
                                                     (retry_count, cmd))
            else:
                break

        log.debug("_do_cmd_resp: Sent command: %s, %s reattempts, expected_prompt=%s, result=%s.",
                  cmd_line, retry_num, expected_prompt, result)

        resp_handler = self._response_handlers.get((self.get_current_state(), cmd), None) or \
            self._response_handlers.get(cmd, None)
        resp_result = None
        if resp_handler:
            resp_result = resp_handler(result, prompt)

        time.sleep(0.3)     # give some time for the instrument connection to keep up

        return resp_result
    def cmd_driver(self, msg):
        """
        Process a command message against the driver. If the command
        exists as a driver attribute, call it passing supplied args and
        kwargs and returning the driver result. Special messages that are
        not forwarded to the driver are:
        'stop_driver_process' - signal to close messaging and terminate.
        'test_events' - populate event queue with test data.
        'process_echo' - echos the message back.
        If the command is not found in the driver, an echo message is
        replied to the client.
        @param msg A driver command message.
        @retval The driver command result.
        """
        cmd = msg.get('cmd', None)
        args = msg.get('args', None)
        kwargs = msg.get('kwargs', None)
        cmd_func = getattr(self.driver, cmd, None)
        log.debug("DriverProcess.cmd_driver(): cmd=%s, cmd_func=%s" %
                  (cmd, cmd_func))
        if cmd == 'stop_driver_process':
            self.stop_messaging()
            return 'stop_driver_process'
        elif cmd == 'test_events':
            events = kwargs['events']
            self.events += events
            reply = 'test_events'
        elif cmd == 'process_echo':
            reply = 'ping from resource ppid:%s, resource:%s' % (str(
                self.ppid), str(self.driver))
            #try:
            #    msg = args[0]
            #except IndexError:
            #    msg = 'no message to echo'
            # reply = 'process_echo: %s' % msg
        elif cmd_func:
            try:
                reply = cmd_func(*args, **kwargs)
            except Exception as e:
                reply = e
                # Command error events are better handled in the agent directly.
                #event = {
                #    'type' : DriverAsyncEvent.ERROR,
                #    'value' : str(e),
                #    'exception' : e,
                #    'time' : time.time()
                #}
                #self.send_event(event)
                if not isinstance(e, InstrumentException):
                    trace = traceback.format_exc()
                    log.critical("Python error, Trace follows: \n%s" % trace)

        else:
            reply = InstrumentCommandException('Unknown driver command.')
            # Command error events are better handled in the agent directly.
            #event = {
            #    'type' : DriverAsyncEvent.ERROR,
            #    'value' : str(reply),
            #    'exception' : reply,
            #    'time' : time.time()
            #}
            #self.send_event(event)

        return reply