Beispiel #1
0
 def stop(self):
     self.process.terminate()
     timeout_secs = 10
     output = ''
     for _ in range(timeout_secs):
         if self.process.poll() is not None:
             break
         time.sleep(1)
     else:
         output += _read_nonblock(self.process.stdout)
         self.process.kill()
         self.logger.error('iio-capture did not terminate gracefully')
         if self.process.poll() is None:
             msg = 'Could not terminate iio-capture:\n{}'
             raise HostError(msg.format(output))
     if self.process.returncode != 15:  # iio-capture exits with 15 when killed
         if sys.version_info[0] == 3:
             output += self.process.stdout.read().decode(
                 sys.stdout.encoding or 'utf-8', 'replace')
         else:
             output += self.process.stdout.read()
         self.logger.info('ACME instrument encountered an error, '
                          'you may want to try rebooting the ACME device:\n'
                          '  ssh root@{} reboot'.format(self.host))
         raise HostError(
             'iio-capture exited with an error ({}), output:\n{}'.format(
                 self.process.returncode, output))
     if not os.path.isfile(self.raw_data_file):
         raise HostError('Output CSV not generated.')
     self.process = None
Beispiel #2
0
    def __init__(
            self,
            target,
            resistor_values,  # pylint: disable=R0914
            labels=None,
            host='localhost',
            port=45677,
            device_id='Dev1',
            v_range=2.5,
            dv_range=0.2,
            sample_rate_hz=10000,
            channel_map=(0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22,
                         23),
            keep_raw=False,
            time_as_clock_boottime=True):
        # pylint: disable=no-member
        super(DaqInstrument, self).__init__(target)
        self.keep_raw = keep_raw
        self._need_reset = True
        self._raw_files = []
        self.tempdir = None
        self.target_boottime_clock_at_start = 0.0
        if DaqClient is None:
            raise HostError(
                'Could not import "daqpower": {}'.format(import_error_mesg))
        if labels is None:
            labels = ['PORT_{}'.format(i) for i in range(len(resistor_values))]
        if len(labels) != len(resistor_values):
            raise ValueError(
                '"labels" and "resistor_values" must be of the same length')
        self.daq_client = DaqClient(host, port)
        try:
            devices = self.daq_client.list_devices()
            if device_id not in devices:
                msg = 'Device "{}" is not found on the DAQ server. Available devices are: "{}"'
                raise ValueError(msg.format(device_id, ', '.join(devices)))
        except Exception as e:
            raise HostError('Problem querying DAQ server: {}'.format(e))

        self.device_config = DeviceConfiguration(
            device_id=device_id,
            v_range=v_range,
            dv_range=dv_range,
            sampling_rate=sample_rate_hz,
            resistor_values=resistor_values,
            channel_map=channel_map,
            labels=labels)
        self.sample_rate_hz = sample_rate_hz
        self.time_as_clock_boottime = time_as_clock_boottime

        self.add_channel('Time', 'time')
        for label in labels:
            for kind in ['power', 'voltage']:
                self.add_channel(label, kind)

        if time_as_clock_boottime:
            host_path = os.path.join(PACKAGE_BIN_DIRECTORY, self.target.abi,
                                     'get_clock_boottime')
            self.clock_boottime_cmd = self.target.install_if_needed(
                host_path, search_system_binaries=False)
Beispiel #3
0
 def _validate_image_bundle(self, image_bundle):
     if not tarfile.is_tarfile(image_bundle):
         raise HostError('File {} is not a tarfile'.format(image_bundle))
     with tarfile.open(image_bundle) as tar:
         files = [tf.name for tf in tar.getmembers()]
         if not any(pf in files for pf in (self.partitions_file_name, '{}/{}'.format(files[0], self.partitions_file_name))):
             HostError('Image bundle does not contain the required partition file (see documentation)')
Beispiel #4
0
def adb_get_device(timeout=None, adb_server=None):
    """
    Returns the serial number of a connected android device.

    If there are more than one device connected to the machine, or it could not
    find any device connected, :class:`devlib.exceptions.HostError` is raised.
    """
    # TODO this is a hacky way to issue a adb command to all listed devices

    # Ensure server is started so the 'daemon started successfully' message
    # doesn't confuse the parsing below
    adb_command(None, 'start-server', adb_server=adb_server)

    # The output of calling adb devices consists of a heading line then
    # a list of the devices sperated by new line
    # The last line is a blank new line. in otherwords, if there is a device found
    # then the output length is 2 + (1 for each device)
    start = time.time()
    while True:
        output = adb_command(None, "devices",
                             adb_server=adb_server).splitlines()  # pylint: disable=E1103
        output_length = len(output)
        if output_length == 3:
            # output[1] is the 2nd line in the output which has the device name
            # Splitting the line by '\t' gives a list of two indexes, which has
            # device serial in 0 number and device type in 1.
            return output[1].split('\t')[0]
        elif output_length > 3:
            message = '{} Android devices found; either explicitly specify ' +\
                      'the device you want, or make sure only one is connected.'
            raise HostError(message.format(output_length - 2))
        else:
            if timeout < time.time() - start:
                raise HostError('No device is connected and available')
            time.sleep(1)
Beispiel #5
0
 def __try_import(path):
     try:
         return __import__(path, {}, {}, [''])
     except Exception as e:
         he = HostError('Could not load {}: {}'.format(path, str(e)))
         he.module = path
         he.exc_info = sys.exc_info()
         he.orig_exc = e
         raise he
Beispiel #6
0
 def __try_import(path):
     try:
         return __import__(path, {}, {}, [''])
     except Exception as e:
         he = HostError('Could not load {}: {}'.format(path, str(e)))
         he.module = path
         he.exc_info = sys.exc_info()
         he.orig_exc = e
         raise he
Beispiel #7
0
    def __init__(
        self,
        target,
        events=None,
        buffer_size=None,
        buffer_size_step=1000,
        buffer_size_file='/sys/kernel/debug/tracing/buffer_size_kb',
        marker_file='/sys/kernel/debug/tracing/trace_marker',
        automark=True,
        autoreport=True,
        autoview=False,
        no_install=False,
    ):
        super(FtraceCollector, self).__init__(target)
        self.events = events if events is not None else DEFAULT_EVENTS
        self.buffer_size = buffer_size
        self.buffer_size_step = buffer_size_step
        self.buffer_size_file = buffer_size_file
        self.marker_file = marker_file
        self.automark = automark
        self.autoreport = autoreport
        self.autoview = autoview
        self.target_output_file = os.path.join(self.target.working_directory,
                                               OUTPUT_TRACE_FILE)
        self.target_binary = None
        self.host_binary = None
        self.start_time = None
        self.stop_time = None
        self.event_string = _build_trace_events(self.events)
        self._reset_needed = True

        self.host_binary = which('trace-cmd')
        self.kernelshark = which('kernelshark')

        if not self.target.is_rooted:
            raise TargetError(
                'trace-cmd instrument cannot be used on an unrooted device.')
        if self.autoreport and self.host_binary is None:
            raise HostError(
                'trace-cmd binary must be installed on the host if autoreport=True.'
            )
        if self.autoview and self.kernelshark is None:
            raise HostError(
                'kernelshark binary must be installed on the host if autoview=True.'
            )
        if not no_install:
            host_file = os.path.join(PACKAGE_BIN_DIRECTORY, self.target.abi,
                                     'trace-cmd')
            self.target_binary = self.target.install(host_file)
        else:
            if not self.target.is_installed('trace-cmd'):
                raise TargetError(
                    'No trace-cmd found on device and no_install=True is specified.'
                )
            self.target_binary = 'trace-cmd'
Beispiel #8
0
def get_mapping(base_dir, partition_file):
    mapping = {}
    with open(partition_file) as pf:
        for line in pf:
            pair = line.split()
            if len(pair) != 2:
                HostError('partitions.txt is not properly formated')
            image_path = os.path.join(base_dir, pair[1])
            if not os.path.isfile(expand_path(image_path)):
                HostError('file {} was not found in the bundle or was misplaced'.format(pair[1]))
            mapping[pair[0]] = image_path
    return mapping
Beispiel #9
0
    def __init__(
        self,
        target,
        resistor_values,  # pylint: disable=R0914
        labels=None,
        host='localhost',
        port=45677,
        device_id='Dev1',
        v_range=2.5,
        dv_range=0.2,
        sample_rate_hz=10000,
        channel_map=(0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23),
    ):
        # pylint: disable=no-member
        super(DaqInstrument, self).__init__(target)
        self._need_reset = True
        self._raw_files = []
        if execute_command is None:
            raise HostError(
                'Could not import "daqpower": {}'.format(import_error_mesg))
        if labels is None:
            labels = [
                'PORT_{}'.format(i) for i in xrange(len(resistor_values))
            ]
        if len(labels) != len(resistor_values):
            raise ValueError(
                '"labels" and "resistor_values" must be of the same length')
        self.server_config = ServerConfiguration(host=host, port=port)
        result = self.execute('list_devices')
        if result.status == Status.OK:
            if device_id not in result.data:
                raise ValueError(
                    'Device "{}" is not found on the DAQ server.'.format(
                        device_id))
        elif result.status != Status.OKISH:
            raise HostError('Problem querying DAQ server: {}'.format(
                result.message))

        self.device_config = DeviceConfiguration(
            device_id=device_id,
            v_range=v_range,
            dv_range=dv_range,
            sampling_rate=sample_rate_hz,
            resistor_values=resistor_values,
            channel_map=channel_map,
            labels=labels)
        self.sample_rate_hz = sample_rate_hz

        for label in labels:
            for kind in ['power', 'voltage']:
                self.add_channel(label, kind)
Beispiel #10
0
def validate_image_bundle(bundle):
    if not tarfile.is_tarfile(bundle):
        raise HostError(
            'Image bundle {} does not appear to be a valid TAR file.'.format(
                bundle))
    with tarfile.open(bundle) as tar:
        try:
            tar.getmember('config.txt')
        except KeyError:
            try:
                tar.getmember('./config.txt')
            except KeyError:
                msg = 'Tarball {} does not appear to be a valid image bundle (did not see config.txt).'
                raise HostError(msg.format(bundle))
Beispiel #11
0
def _give_password(password, command):
    if not sshpass:
        raise HostError(
            'Must have sshpass installed on the host in order to use password-based auth.'
        )
    pass_string = "sshpass -p '{}' ".format(password)
    return pass_string + command
Beispiel #12
0
    def stop(self):
        process = self.process
        self.process = None
        if not process:
            raise RuntimeError('Monsoon script not started')

        process.poll()
        if process.returncode is not None:
            stdout, stderr = process.communicate()
            raise HostError(
                'Monsoon script exited unexpectedly with exit code {}.\n'
                'stdout:\n{}\nstderr:\n{}'.format(process.returncode, stdout,
                                                  stderr))

        process.send_signal(signal.SIGINT)

        stderr = process.stderr.read()

        self.buffer_file.close()
        with open(self.buffer_file.name) as f:
            stdout = f.read()
        os.remove(self.buffer_file.name)
        self.buffer_file = None

        self.output = (stdout, stderr)
        os.system(self.monsoon_bin + ' --usbpassthrough on')

        # Wait for USB connection to be restored
        print('waiting for usb connection to be back')
        os.system('adb wait-for-device')
Beispiel #13
0
    def __init__(
        self,
        target,
        resistor_values,
        labels=None,
        device_entry='/dev/ttyACM0',
    ):
        super(EnergyProbeInstrument, self).__init__(target)
        self.resistor_values = resistor_values
        if labels is not None:
            self.labels = labels
        else:
            self.labels = [
                'PORT_{}'.format(i) for i in xrange(len(resistor_values))
            ]
        self.device_entry = device_entry
        self.caiman = which('caiman')
        if self.caiman is None:
            raise HostError('caiman must be installed on the host '
                            '(see https://github.com/ARM-software/caiman)')
        if pandas is None:
            self.logger.info(
                "pandas package will significantly speed up this instrument")
            self.logger.info("to install it try: pip install pandas")
        self.attributes_per_sample = 3
        self.bytes_per_sample = self.attributes_per_sample * 4
        self.attributes = ['power', 'voltage', 'current']
        self.command = None
        self.raw_output_directory = None
        self.process = None

        for label in self.labels:
            for kind in self.attributes:
                self.add_channel(label, kind)
Beispiel #14
0
def get_connection(timeout, init_dtr=None, logcls=SerialLogger,
                   logfile=None, *args, **kwargs):
    if init_dtr is not None:
        kwargs['dsrdtr'] = True
    try:
        conn = serial.Serial(*args, **kwargs)
    except serial.SerialException as e:
        raise HostError(str(e))
    if init_dtr is not None:
        conn.setDTR(init_dtr)
    conn.nonblocking()
    conn.flushOutput()
    target = fdpexpect.fdspawn(conn.fileno(), timeout=timeout, logfile=logfile)
    target.logfile_read = logcls('read')
    target.logfile_send = logcls('send')

    # Monkey-patching sendline to introduce a short delay after
    # chacters are sent to the serial. If two sendline s are issued
    # one after another the second one might start putting characters
    # into the serial device before the first one has finished, causing
    # corruption. The delay prevents that.
    tsln = target.sendline

    def sendline(x):
        tsln(x)
        time.sleep(0.1)

    target.sendline = sendline
    return target, conn
Beispiel #15
0
    def __init__(self, target,
                 categories=None,
                 buffer_size=None,
                 strict=False):

        super(SystraceCollector, self).__init__(target)

        self.categories = categories or DEFAULT_CATEGORIES
        self.buffer_size = buffer_size

        self._systrace_process = None
        self._tmpfile = None

        # Try to find a systrace binary
        self.systrace_binary = None

        platform_tools = devlib.utils.android.platform_tools
        systrace_binary_path = os.path.join(platform_tools, 'systrace', 'systrace.py')
        if not os.path.isfile(systrace_binary_path):
            raise HostError('Could not find any systrace binary under {}'.format(platform_tools))

        self.systrace_binary = systrace_binary_path

        # Filter the requested categories
        for category in self.categories:
            if category not in self.available_categories:
                message = 'Category [{}] not available for tracing'.format(category)
                if strict:
                    raise TargetStableError(message)
                self.logger.warning(message)

        self.categories = list(set(self.categories) & set(self.available_categories))
        if not self.categories:
            raise TargetStableError('None of the requested categories are available')
Beispiel #16
0
    def _goto_dump(self, stats_file, target_dump):
        if target_dump < 0:
            raise HostError('Cannot go to dump {}'.format(target_dump))

        # Go to required dump quickly if it was visited before
        if target_dump in self._dump_pos_cache:
            stats_file.seek(self._dump_pos_cache[target_dump])
            return target_dump
        # Or start from the closest dump already visited before the required one
        prev_dumps = filter(lambda x: x < target_dump, self._dump_pos_cache.keys())
        curr_dump = max(prev_dumps)
        curr_pos = self._dump_pos_cache[curr_dump]
        stats_file.seek(curr_pos)

        # And iterate until target_dump
        dump_iterator = iter_statistics_dump(stats_file)
        while curr_dump < target_dump:
            try:
                next(dump_iterator)
            except StopIteration:
                break
            # End of passed dump is beginning og next one
            curr_pos = stats_file.tell()
            curr_dump += 1
        self._dump_pos_cache[curr_dump] = curr_pos
        return curr_dump
Beispiel #17
0
    def __init__(
        self,
        target,
        resistor_values,
        labels=None,
        device_entry='/dev/ttyACM0',
    ):
        super(EnergyProbeInstrument, self).__init__(target)
        self.resistor_values = resistor_values
        if labels is not None:
            self.labels = labels
        else:
            self.labels = [
                'PORT_{}'.format(i) for i in range(len(resistor_values))
            ]
        self.device_entry = device_entry
        self.caiman = which('caiman')
        if self.caiman is None:
            raise HostError('caiman must be installed on the host '
                            '(see https://github.com/ARM-software/caiman)')
        self.attributes_per_sample = 3
        self.bytes_per_sample = self.attributes_per_sample * 4
        self.attributes = ['power', 'voltage', 'current']
        self.command = None
        self.raw_output_directory = None
        self.process = None
        self.sample_rate_hz = 10000  # Determined empirically
        self.raw_data_file = None

        for label in self.labels:
            for kind in self.attributes:
                self.add_channel(label, kind)
Beispiel #18
0
    def __init__(self, target, apk=None, service='.TrafficMetricsService'):
        """
        Additional paramerter:

        :apk: Path to the APK file that contains ``com.arm.devlab.netstats``
              package. If not specified, it will be assumed that an APK with
              name "netstats.apk" is located in the same directory as the
              Python module for the instrument.
        :service: Name of the service to be launched. This service must be
                  present in the APK.

        """
        if target.os != 'android':
            raise TargetError(
                'netstats insturment only supports Android targets')
        if apk is None:
            apk = os.path.join(THIS_DIR, 'netstats.apk')
        if not os.path.isfile(apk):
            raise HostError(
                'APK for netstats instrument does not exist ({})'.format(apk))
        super(NetstatsInstrument, self).__init__(target)
        self.apk = apk
        self.package = ApkInfo(self.apk).package
        self.service = service
        self.tag = None
        self.command = None
        self.stop_command = 'am kill {}'.format(self.package)

        for package in self.target.list_packages():
            self.add_channel(package, 'tx')
            self.add_channel(package, 'rx')
Beispiel #19
0
def adb_connect(device, timeout=None, attempts=MAX_ATTEMPTS, adb_server=None):
    _check_env()
    tries = 0
    output = None
    while tries <= attempts:
        tries += 1
        if device:
            if "." in device:  # Connect is required only for ADB-over-IP
                # ADB does not automatically remove a network device from it's
                # devices list when the connection is broken by the remote, so the
                # adb connection may have gone "stale", resulting in adb blocking
                # indefinitely when making calls to the device. To avoid this,
                # always disconnect first.
                adb_disconnect(device, adb_server)
                adb_cmd = get_adb_command(None, 'connect', adb_server)
                command = '{} {}'.format(adb_cmd, quote(device))
                logger.debug(command)
                output, _ = check_output(command, shell=True, timeout=timeout)
        if _ping(device, adb_server):
            break
        time.sleep(10)
    else:  # did not connect to the device
        message = 'Could not connect to {}'.format(device or 'a device')
        if output:
            message += '; got: "{}"'.format(output)
        raise HostError(message)
Beispiel #20
0
 def _scp(self, source, dest, timeout=30):
     # NOTE: the version of scp in Ubuntu 12.04 occasionally (and bizarrely)
     # fails to connect to a device if port is explicitly specified using -P
     # option, even if it is the default port, 22. To minimize this problem,
     # only specify -P for scp if the port is *not* the default.
     port_string = '-P {}'.format(quote(str(
         self.port))) if (self.port and self.port != 22) else ''
     keyfile_string = '-i {}'.format(quote(
         self.keyfile)) if self.keyfile else ''
     options = " ".join(
         ["-o{}={}".format(key, val) for key, val in self.options.items()])
     command = '{} {} -r {} {} {} {}'.format(scp, options, keyfile_string,
                                             port_string, quote(source),
                                             quote(dest))
     command_redacted = command
     logger.debug(command)
     if self.password:
         command, command_redacted = _give_password(self.password, command)
     try:
         check_output(command, timeout=timeout, shell=True)
     except subprocess.CalledProcessError as e:
         raise_from(
             HostError("Failed to copy file with '{}'. Output:\n{}".format(
                 command_redacted, e.output)), None)
     except TimeoutError as e:
         raise TimeoutError(command_redacted, e.output)
Beispiel #21
0
    def stop(self):
        process = self.process
        self.process = None
        if not process:
            raise RuntimeError('Monsoon script not started')

        process.poll()
        if process.returncode is not None:
            stdout, stderr = process.communicate()
            if sys.version_info[0] == 3:
                stdout = stdout.encode(sys.stdout.encoding)
                stderr = stderr.encode(sys.stdout.encoding)
            raise HostError(
                'Monsoon script exited unexpectedly with exit code {}.\n'
                'stdout:\n{}\nstderr:\n{}'.format(process.returncode, stdout,
                                                  stderr))

        process.send_signal(signal.SIGINT)

        stderr = process.stderr.read()

        self.buffer_file.close()
        with open(self.buffer_file.name) as f:
            stdout = f.read()
        os.remove(self.buffer_file.name)
        self.buffer_file = None

        self.output = (stdout, stderr)
 def report(self, binfile, destfile):
     # To get the output of trace.dat, trace-cmd must be installed
     # This is done host-side because the generated file is very large
     try:
         command = '{} report {} > {}'.format(self.host_binary, binfile,
                                              destfile)
         self.logger.debug(command)
         process = subprocess.Popen(command,
                                    stderr=subprocess.PIPE,
                                    shell=True)
         _, error = process.communicate()
         if process.returncode:
             raise TargetError(
                 'trace-cmd returned non-zero exit code {}'.format(
                     process.returncode))
         if error:
             # logged at debug level, as trace-cmd always outputs some
             # errors that seem benign.
             self.logger.debug(error)
         if os.path.isfile(destfile):
             self.logger.debug('Verifying traces.')
             with open(destfile) as fh:
                 for line in fh:
                     if 'EVENTS DROPPED' in line:
                         self.logger.warning('Dropped events detected.')
                         break
                 else:
                     self.logger.debug('Trace verified.')
         else:
             self.logger.warning('Could not generate trace.txt.')
     except OSError:
         raise HostError(
             'Could not find trace-cmd. Please make sure it is installed and is in PATH.'
         )
Beispiel #23
0
    def get_data(self, output_file):
        temp_file = tempfile.mktemp()
        self.target.pull(self.on_target_file, temp_file)
        self.target.remove(self.on_target_file)

        with open(temp_file, 'rb') as fh:
            reader = csv.reader(fh)
            headings = reader.next()

            # Figure out which columns from the collected csv we actually want
            select_columns = []
            for chan in self.active_channels:
                try:
                    select_columns.append(headings.index(chan.name))
                except ValueError:
                    raise HostError('Channel "{}" is not in {}'.format(
                        chan.name, temp_file))

            with open(output_file, 'wb') as wfh:
                write_headings = [
                    '{}_{}'.format(c.site, c.kind)
                    for c in self.active_channels
                ]
                writer = csv.writer(wfh)
                writer.writerow(write_headings)
                for row in reader:
                    write_row = [row[c] for c in select_columns]
                    writer.writerow(write_row)

        return MeasurementsCsv(output_file, self.active_channels)
Beispiel #24
0
 def reset(self, sites=None, kinds=None):
     super(DaqInstrument, self).reset(sites, kinds)
     self.execute('close')
     result = self.execute('configure', config=self.device_config)
     if not result.status == Status.OK:  # pylint: disable=no-member
         raise HostError(result.message)
     self._need_reset = False
Beispiel #25
0
 def push(self, source, dest, timeout=None):
     if timeout is None:
         timeout = self.timeout
     command = "push '{}' '{}'".format(source, dest)
     if not os.path.exists(source):
         raise HostError('No such file "{}"'.format(source))
     return adb_command(self.device, command, timeout=timeout, adb_server=self.adb_server)
Beispiel #26
0
def _check_env():
    global ssh, scp, sshpass  # pylint: disable=global-statement
    if not ssh:
        ssh = which('ssh')
        scp = which('scp')
        sshpass = which('sshpass')
    if not (ssh and scp):
        raise HostError('OpenSSH must be installed on the host.')
Beispiel #27
0
def _init_common(env):
    logger.debug('ANDROID_HOME: {}'.format(env.android_home))
    build_tools_directory = os.path.join(env.android_home, 'build-tools')
    if not os.path.isdir(build_tools_directory):
        msg = '''ANDROID_HOME ({}) does not appear to have valid Android SDK install
                 (cannot find build-tools)'''
        raise HostError(msg.format(env.android_home))
    versions = os.listdir(build_tools_directory)
    for version in reversed(sorted(versions)):
        aapt_path = os.path.join(build_tools_directory, version, 'aapt')
        if os.path.isfile(aapt_path):
            logger.debug('Using aapt for version {}'.format(version))
            env.aapt = aapt_path
            break
    else:
        raise HostError('aapt not found. Please make sure at least one Android '
                        'platform is installed.')
Beispiel #28
0
def _give_password(password, command):
    if not sshpass:
        raise HostError(
            'Must have sshpass installed on the host in order to use password-based auth.'
        )
    pass_template = "sshpass -p {} "
    pass_string = pass_template.format(quote(password))
    redacted_string = pass_template.format(quote('<redacted>'))
    return (pass_string + command, redacted_string + command)
Beispiel #29
0
 def stop(self):
     self.process.poll()
     if self.process.returncode is not None:
         stdout, stderr = self.process.communicate()
         raise HostError(
             'Energy Probe: Caiman exited unexpectedly with exit code {}.\n'
             'stdout:\n{}\nstderr:\n{}'.format(self.process.returncode,
                                               stdout, stderr))
     os.killpg(self.process.pid, signal.SIGINT)
Beispiel #30
0
    def get_data(self, outfile):  # pylint: disable=R0914
        self.tempdir = tempfile.mkdtemp(prefix='daq-raw-')
        self.daq_client.get_data(self.tempdir)
        raw_file_map = {}
        for entry in os.listdir(self.tempdir):
            site = os.path.splitext(entry)[0]
            path = os.path.join(self.tempdir, entry)
            raw_file_map[site] = path
            self._raw_files.append(path)

        active_sites = unique([c.site for c in self.active_channels])
        file_handles = []
        try:
            site_readers = {}
            for site in active_sites:
                try:
                    site_file = raw_file_map[site]
                    reader, fh = create_reader(site_file)
                    site_readers[site] = reader
                    file_handles.append(fh)
                except KeyError:
                    if not site.startswith("Time"):
                        message = 'Could not get DAQ trace for {}; Obtained traces are in {}'
                        raise HostError(message.format(site, self.tempdir))

            # The first row is the headers
            channel_order = ['Time_time']
            for site, reader in site_readers.items():
                channel_order.extend(
                    ['{}_{}'.format(site, kind) for kind in next(reader)])

            def _read_rows():
                row_iter = zip_longest(*site_readers.values(),
                                       fillvalue=(None, None))
                for raw_row in row_iter:
                    raw_row = list(chain.from_iterable(raw_row))
                    raw_row.insert(0, _read_rows.row_time_s)
                    yield raw_row
                    _read_rows.row_time_s += 1.0 / self.sample_rate_hz

            _read_rows.row_time_s = self.target_boottime_clock_at_start

            with csvwriter(outfile) as writer:
                field_names = [c.label for c in self.active_channels]
                writer.writerow(field_names)
                for raw_row in _read_rows():
                    row = [
                        raw_row[channel_order.index(f)] for f in field_names
                    ]
                    writer.writerow(row)

            return MeasurementsCsv(outfile, self.active_channels,
                                   self.sample_rate_hz)
        finally:
            for fh in file_handles:
                fh.close()
Beispiel #31
0
    def get_data(self, outfile):  # pylint: disable=R0914
        tempdir = tempfile.mkdtemp(prefix='daq-raw-')
        self.execute('get_data', output_directory=tempdir)
        raw_file_map = {}
        for entry in os.listdir(tempdir):
            site = os.path.splitext(entry)[0]
            path = os.path.join(tempdir, entry)
            raw_file_map[site] = path
            self._raw_files.append(path)

        active_sites = unique([c.site for c in self.active_channels])
        file_handles = []
        try:
            site_readers = {}
            for site in active_sites:
                try:
                    site_file = raw_file_map[site]
                    fh = open(site_file, 'rb')
                    site_readers[site] = csv.reader(fh)
                    file_handles.append(fh)
                except KeyError:
                    message = 'Could not get DAQ trace for {}; Obtained traces are in {}'
                    raise HostError(message.format(site, tempdir))

            # The first row is the headers
            channel_order = []
            for site, reader in site_readers.iteritems():
                channel_order.extend(
                    ['{}_{}'.format(site, kind) for kind in reader.next()])

            def _read_next_rows():
                parts = []
                for reader in site_readers.itervalues():
                    try:
                        parts.extend(reader.next())
                    except StopIteration:
                        parts.extend([None, None])
                return list(chain(parts))

            with open(outfile, 'wb') as wfh:
                field_names = [c.label for c in self.active_channels]
                writer = csv.writer(wfh)
                writer.writerow(field_names)
                raw_row = _read_next_rows()
                while any(raw_row):
                    row = [
                        raw_row[channel_order.index(f)] for f in field_names
                    ]
                    writer.writerow(row)
                    raw_row = _read_next_rows()

            return MeasurementsCsv(outfile, self.active_channels,
                                   self.sample_rate_hz)
        finally:
            for fh in file_handles:
                fh.close()