2015-10-09 09:30:04 +01:00
|
|
|
Instrumentation
|
|
|
|
===============
|
|
|
|
|
|
|
|
The ``Instrument`` API provide a consistent way of collecting measurements from
|
|
|
|
a target. Measurements are collected via an instance of a class derived from
|
|
|
|
:class:`Instrument`. An ``Instrument`` allows collection of measurement from one
|
|
|
|
or more channels. An ``Instrument`` may support ``INSTANTANEOUS`` or
|
|
|
|
``CONTINUOUS`` collection, or both.
|
|
|
|
|
|
|
|
Example
|
|
|
|
-------
|
|
|
|
|
|
|
|
The following example shows how to use an instrument to read temperature from an
|
|
|
|
Android target.
|
|
|
|
|
|
|
|
.. code-block:: ipython
|
|
|
|
|
|
|
|
# import and instantiate the Target and the instrument
|
|
|
|
# (note: this assumes exactly one android target connected
|
|
|
|
# to the host machine).
|
|
|
|
In [1]: from devlib import AndroidTarget, HwmonInstrument
|
|
|
|
|
|
|
|
In [2]: t = AndroidTarget()
|
|
|
|
|
|
|
|
In [3]: i = HwmonInstrument(t)
|
|
|
|
|
|
|
|
# Set up the instrument on the Target. In case of HWMON, this is
|
|
|
|
# a no-op, but is included here for completeness.
|
|
|
|
In [4]: i.setup()
|
|
|
|
|
2017-04-26 15:07:33 +01:00
|
|
|
# Find out what the instrument is capable collecting from the
|
2015-10-09 09:30:04 +01:00
|
|
|
# target.
|
|
|
|
In [5]: i.list_channels()
|
|
|
|
Out[5]:
|
|
|
|
[CHAN(battery/temp1, battery_temperature),
|
|
|
|
CHAN(exynos-therm/temp1, exynos-therm_temperature)]
|
|
|
|
|
|
|
|
# Set up a new measurement session, and specify what is to be
|
|
|
|
# collected.
|
|
|
|
In [6]: i.reset(sites=['exynos-therm'])
|
|
|
|
|
|
|
|
# HWMON instrument supports INSTANTANEOUS collection, so invoking
|
2017-04-26 15:07:33 +01:00
|
|
|
# take_measurement() will return a list of measurements take from
|
2015-10-09 09:30:04 +01:00
|
|
|
# each of the channels configured during reset()
|
|
|
|
In [7]: i.take_measurement()
|
|
|
|
Out[7]: [exynos-therm_temperature: 36.0 degrees]
|
|
|
|
|
|
|
|
API
|
|
|
|
---
|
|
|
|
|
|
|
|
Instrument
|
|
|
|
~~~~~~~~~~
|
|
|
|
|
|
|
|
.. class:: Instrument(target, **kwargs)
|
|
|
|
|
|
|
|
An ``Instrument`` allows collection of measurement from one or more
|
|
|
|
channels. An ``Instrument`` may support ``INSTANTANEOUS`` or ``CONTINUOUS``
|
|
|
|
collection, or both.
|
|
|
|
|
|
|
|
.. attribute:: Instrument.mode
|
|
|
|
|
|
|
|
A bit mask that indicates collection modes that are supported by this
|
|
|
|
instrument. Possible values are:
|
|
|
|
|
|
|
|
:INSTANTANEOUS: The instrument supports taking a single sample via
|
|
|
|
``take_measurement()``.
|
|
|
|
:CONTINUOUS: The instrument supports collecting measurements over a
|
2017-08-30 14:55:42 +01:00
|
|
|
period of time via ``start()``, ``stop()``, ``get_data()``,
|
|
|
|
and (optionally) ``get_raw`` methods.
|
2015-10-09 09:30:04 +01:00
|
|
|
|
2017-04-26 15:07:33 +01:00
|
|
|
.. note:: It's possible for one instrument to support more than a single
|
2015-10-09 09:30:04 +01:00
|
|
|
mode.
|
|
|
|
|
|
|
|
.. attribute:: Instrument.active_channels
|
|
|
|
|
|
|
|
Channels that have been activated via ``reset()``. Measurements will only be
|
|
|
|
collected for these channels.
|
|
|
|
|
|
|
|
.. method:: Instrument.list_channels()
|
|
|
|
|
|
|
|
Returns a list of :class:`InstrumentChannel` instances that describe what
|
|
|
|
this instrument can measure on the current target. A channel is a combination
|
|
|
|
of a ``kind`` of measurement (power, temperature, etc) and a ``site`` that
|
|
|
|
indicates where on the target the measurement will be collected from.
|
|
|
|
|
|
|
|
.. method:: Instrument.get_channels(measure)
|
|
|
|
|
|
|
|
Returns channels for a particular ``measure`` type. A ``measure`` can be
|
|
|
|
either a string (e.g. ``"power"``) or a :class:`MeasurmentType` instance.
|
|
|
|
|
|
|
|
.. method:: Instrument.setup(*args, **kwargs)
|
|
|
|
|
|
|
|
This will set up the instrument on the target. Parameters this method takes
|
|
|
|
are particular to subclasses (see documentation for specific instruments
|
|
|
|
below). What actions are performed by this method are also
|
|
|
|
instrument-specific. Usually these will be things like installing
|
|
|
|
executables, starting services, deploying assets, etc. Typically, this method
|
|
|
|
needs to be invoked at most once per reboot of the target (unless
|
|
|
|
``teardown()`` has been called), but see documentation for the instrument
|
|
|
|
you're interested in.
|
|
|
|
|
2017-05-10 11:18:21 +01:00
|
|
|
.. method:: Instrument.reset(sites=None, kinds=None, channels=None)
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
This is used to configure an instrument for collection. This must be invoked
|
2017-05-10 11:18:21 +01:00
|
|
|
before ``start()`` is called to begin collection. This methods sets the
|
|
|
|
``active_channels`` attribute of the ``Instrument``.
|
|
|
|
|
|
|
|
If ``channels`` is provided, it is a list of names of channels to enable and
|
|
|
|
``sites`` and ``kinds`` must both be ``None``.
|
|
|
|
|
|
|
|
Otherwise, if one of ``sites`` or ``kinds`` is provided, all channels
|
|
|
|
matching the given sites or kinds are enabled. If both are provided then all
|
|
|
|
channels of the given kinds at the given sites are enabled.
|
|
|
|
|
|
|
|
If none of ``sites``, ``kinds`` or ``channels`` are provided then all
|
|
|
|
available channels are enabled.
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
.. method:: Instrument.take_measurment()
|
|
|
|
|
|
|
|
Take a single measurement from ``active_channels``. Returns a list of
|
|
|
|
:class:`Measurement` objects (one for each active channel).
|
|
|
|
|
|
|
|
.. note:: This method is only implemented by :class:`Instrument`\ s that
|
2017-01-10 15:35:21 +00:00
|
|
|
support ``INSTANTANEOUS`` measurement.
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
.. method:: Instrument.start()
|
|
|
|
|
|
|
|
Starts collecting measurements from ``active_channels``.
|
|
|
|
|
|
|
|
.. note:: This method is only implemented by :class:`Instrument`\ s that
|
2017-01-10 15:35:21 +00:00
|
|
|
support ``CONTINUOUS`` measurement.
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
.. method:: Instrument.stop()
|
|
|
|
|
|
|
|
Stops collecting measurements from ``active_channels``. Must be called after
|
|
|
|
:func:`start()`.
|
|
|
|
|
|
|
|
.. note:: This method is only implemented by :class:`Instrument`\ s that
|
2017-01-10 15:35:21 +00:00
|
|
|
support ``CONTINUOUS`` measurement.
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
.. method:: Instrument.get_data(outfile)
|
|
|
|
|
2017-04-26 15:07:33 +01:00
|
|
|
Write collected data into ``outfile``. Must be called after :func:`stop()`.
|
2015-10-09 09:30:04 +01:00
|
|
|
Data will be written in CSV format with a column for each channel and a row
|
2017-04-26 15:07:33 +01:00
|
|
|
for each sample. Column heading will be channel, labels in the form
|
2017-01-10 15:35:21 +00:00
|
|
|
``<site>_<kind>`` (see :class:`InstrumentChannel`). The order of the columns
|
2015-10-09 09:30:04 +01:00
|
|
|
will be the same as the order of channels in ``Instrument.active_channels``.
|
|
|
|
|
2017-08-18 17:22:47 +01:00
|
|
|
If reporting timestamps, one channel must have a ``site`` named ``"timestamp"``
|
|
|
|
and a ``kind`` of a :class:`MeasurmentType` of an appropriate time unit which will
|
|
|
|
be used, if appropriate, during any post processing.
|
|
|
|
|
|
|
|
.. note:: Currently supported time units are seconds, milliseconds and
|
|
|
|
microseconds, other units can also be used if an appropriate
|
|
|
|
conversion is provided.
|
|
|
|
|
2015-10-09 09:30:04 +01:00
|
|
|
This returns a :class:`MeasurementCsv` instance associated with the outfile
|
|
|
|
that can be used to stream :class:`Measurement`\ s lists (similar to what is
|
|
|
|
returned by ``take_measurement()``.
|
|
|
|
|
|
|
|
.. note:: This method is only implemented by :class:`Instrument`\ s that
|
2017-01-10 15:35:21 +00:00
|
|
|
support ``CONTINUOUS`` measurement.
|
2015-10-09 09:30:04 +01:00
|
|
|
|
2017-08-30 14:55:42 +01:00
|
|
|
.. method:: Instrument.get_raw()
|
|
|
|
|
|
|
|
Returns a list of paths to files containing raw output from the underlying
|
|
|
|
source(s) that is used to produce the data CSV. If now raw output is
|
|
|
|
generated or saved, an empty list will be returned. The format of the
|
|
|
|
contents of the raw files is entirely source-dependent.
|
|
|
|
|
2017-04-26 15:07:05 +01:00
|
|
|
.. attribute:: Instrument.sample_rate_hz
|
|
|
|
|
|
|
|
Sample rate of the instrument in Hz. Assumed to be the same for all channels.
|
|
|
|
|
|
|
|
.. note:: This attribute is only provided by :class:`Instrument`\ s that
|
2017-08-07 15:39:38 +01:00
|
|
|
support ``CONTINUOUS`` measurement.
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
Instrument Channel
|
|
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
.. class:: InstrumentChannel(name, site, measurement_type, **attrs)
|
|
|
|
|
|
|
|
An :class:`InstrumentChannel` describes a single type of measurement that may
|
|
|
|
be collected by an :class:`Instrument`. A channel is primarily defined by a
|
|
|
|
``site`` and a ``measurement_type``.
|
|
|
|
|
|
|
|
A ``site`` indicates where on the target a measurement is collected from
|
2017-01-10 15:35:21 +00:00
|
|
|
(e.g. a voltage rail or location of a sensor).
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
A ``measurement_type`` is an instance of :class:`MeasurmentType` that
|
2017-01-10 15:35:21 +00:00
|
|
|
describes what sort of measurement this is (power, temperature, etc). Each
|
|
|
|
measurement type has a standard unit it is reported in, regardless of an
|
2015-10-09 09:30:04 +01:00
|
|
|
instrument used to collect it.
|
|
|
|
|
|
|
|
A channel (i.e. site/measurement_type combination) is unique per instrument,
|
|
|
|
however there may be more than one channel associated with one site (e.g. for
|
2017-01-10 15:35:21 +00:00
|
|
|
both voltage and power).
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
It should not be assumed that any site/measurement_type combination is valid.
|
|
|
|
The list of available channels can queried with
|
|
|
|
:func:`Instrument.list_channels()`.
|
|
|
|
|
|
|
|
.. attribute:: InstrumentChannel.site
|
|
|
|
|
2017-01-10 15:35:21 +00:00
|
|
|
The name of the "site" from which the measurements are collected (e.g. voltage
|
2015-10-09 09:30:04 +01:00
|
|
|
rail, sensor, etc).
|
|
|
|
|
|
|
|
.. attribute:: InstrumentChannel.kind
|
|
|
|
|
2017-01-10 15:35:21 +00:00
|
|
|
A string indicating the type of measurement that will be collected. This is
|
2015-10-09 09:30:04 +01:00
|
|
|
the ``name`` of the :class:`MeasurmentType` associated with this channel.
|
|
|
|
|
|
|
|
.. attribute:: InstrumentChannel.units
|
|
|
|
|
2017-01-10 15:35:21 +00:00
|
|
|
Units in which measurement will be reported. this is determined by the
|
2015-10-09 09:30:04 +01:00
|
|
|
underlying :class:`MeasurmentType`.
|
|
|
|
|
|
|
|
.. attribute:: InstrumentChannel.label
|
|
|
|
|
2017-01-10 15:35:21 +00:00
|
|
|
A label that can be attached to measurements associated with with channel.
|
2015-10-09 09:30:04 +01:00
|
|
|
This is constructed with ::
|
|
|
|
|
|
|
|
'{}_{}'.format(self.site, self.kind)
|
|
|
|
|
|
|
|
|
|
|
|
Measurement Types
|
|
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
In order to make instruments easer to use, and to make it easier to swap them
|
|
|
|
out when necessary (e.g. change method of collecting power), a number of
|
|
|
|
standard measurement types are defined. This way, for example, power will always
|
|
|
|
be reported as "power" in Watts, and never as "pwr" in milliWatts. Currently
|
|
|
|
defined measurement types are
|
|
|
|
|
|
|
|
|
2017-08-18 17:22:47 +01:00
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| name | units | category |
|
|
|
|
+=============+=============+===============+
|
2017-09-07 14:26:04 +01:00
|
|
|
| count | count | |
|
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| percent | percent | |
|
2017-08-18 17:22:47 +01:00
|
|
|
+-------------+-------------+---------------+
|
2017-08-30 14:27:03 +01:00
|
|
|
| time_us | microseconds| time |
|
2017-08-18 17:22:47 +01:00
|
|
|
+-------------+-------------+---------------+
|
2017-08-30 14:27:03 +01:00
|
|
|
| time_ms | milliseconds| time |
|
2017-08-18 17:22:47 +01:00
|
|
|
+-------------+-------------+---------------+
|
2017-09-07 14:26:04 +01:00
|
|
|
| temperature | degrees | thermal |
|
2017-08-18 17:22:47 +01:00
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| power | watts | power/energy |
|
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| voltage | volts | power/energy |
|
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| current | amps | power/energy |
|
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| energy | joules | power/energy |
|
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| tx | bytes | data transfer |
|
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| rx | bytes | data transfer |
|
|
|
|
+-------------+-------------+---------------+
|
|
|
|
| tx/rx | bytes | data transfer |
|
|
|
|
+-------------+-------------+---------------+
|
2015-10-09 09:30:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
.. instruments:
|
|
|
|
|
|
|
|
Available Instruments
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
This section lists instruments that are currently part of devlib.
|
|
|
|
|
|
|
|
TODO
|