Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 1 | Instrumentation |
| 2 | =============== |
| 3 | |
| 4 | The ``Instrument`` API provide a consistent way of collecting measurements from |
| 5 | a target. Measurements are collected via an instance of a class derived from |
| 6 | :class:`Instrument`. An ``Instrument`` allows collection of measurement from one |
| 7 | or more channels. An ``Instrument`` may support ``INSTANTANEOUS`` or |
| 8 | ``CONTINUOUS`` collection, or both. |
| 9 | |
| 10 | Example |
| 11 | ------- |
| 12 | |
| 13 | The following example shows how to use an instrument to read temperature from an |
| 14 | Android target. |
| 15 | |
| 16 | .. code-block:: ipython |
| 17 | |
| 18 | # import and instantiate the Target and the instrument |
| 19 | # (note: this assumes exactly one android target connected |
| 20 | # to the host machine). |
| 21 | In [1]: from devlib import AndroidTarget, HwmonInstrument |
| 22 | |
| 23 | In [2]: t = AndroidTarget() |
| 24 | |
| 25 | In [3]: i = HwmonInstrument(t) |
| 26 | |
| 27 | # Set up the instrument on the Target. In case of HWMON, this is |
| 28 | # a no-op, but is included here for completeness. |
| 29 | In [4]: i.setup() |
| 30 | |
Brendan Jackman | fc81477 | 2017-04-26 15:07:33 +0100 | [diff] [blame] | 31 | # Find out what the instrument is capable collecting from the |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 32 | # target. |
| 33 | In [5]: i.list_channels() |
| 34 | Out[5]: |
| 35 | [CHAN(battery/temp1, battery_temperature), |
| 36 | CHAN(exynos-therm/temp1, exynos-therm_temperature)] |
| 37 | |
| 38 | # Set up a new measurement session, and specify what is to be |
| 39 | # collected. |
| 40 | In [6]: i.reset(sites=['exynos-therm']) |
| 41 | |
| 42 | # HWMON instrument supports INSTANTANEOUS collection, so invoking |
Brendan Jackman | fc81477 | 2017-04-26 15:07:33 +0100 | [diff] [blame] | 43 | # take_measurement() will return a list of measurements take from |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 44 | # each of the channels configured during reset() |
| 45 | In [7]: i.take_measurement() |
| 46 | Out[7]: [exynos-therm_temperature: 36.0 degrees] |
| 47 | |
| 48 | API |
| 49 | --- |
| 50 | |
| 51 | Instrument |
| 52 | ~~~~~~~~~~ |
| 53 | |
| 54 | .. class:: Instrument(target, **kwargs) |
| 55 | |
| 56 | An ``Instrument`` allows collection of measurement from one or more |
| 57 | channels. An ``Instrument`` may support ``INSTANTANEOUS`` or ``CONTINUOUS`` |
| 58 | collection, or both. |
| 59 | |
| 60 | .. attribute:: Instrument.mode |
| 61 | |
| 62 | A bit mask that indicates collection modes that are supported by this |
| 63 | instrument. Possible values are: |
| 64 | |
| 65 | :INSTANTANEOUS: The instrument supports taking a single sample via |
| 66 | ``take_measurement()``. |
| 67 | :CONTINUOUS: The instrument supports collecting measurements over a |
| 68 | period of time via ``start()``, ``stop()``, and |
| 69 | ``get_data()`` methods. |
| 70 | |
Brendan Jackman | fc81477 | 2017-04-26 15:07:33 +0100 | [diff] [blame] | 71 | .. note:: It's possible for one instrument to support more than a single |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 72 | mode. |
| 73 | |
| 74 | .. attribute:: Instrument.active_channels |
| 75 | |
| 76 | Channels that have been activated via ``reset()``. Measurements will only be |
| 77 | collected for these channels. |
| 78 | |
| 79 | .. method:: Instrument.list_channels() |
| 80 | |
| 81 | Returns a list of :class:`InstrumentChannel` instances that describe what |
| 82 | this instrument can measure on the current target. A channel is a combination |
| 83 | of a ``kind`` of measurement (power, temperature, etc) and a ``site`` that |
| 84 | indicates where on the target the measurement will be collected from. |
| 85 | |
| 86 | .. method:: Instrument.get_channels(measure) |
| 87 | |
| 88 | Returns channels for a particular ``measure`` type. A ``measure`` can be |
| 89 | either a string (e.g. ``"power"``) or a :class:`MeasurmentType` instance. |
| 90 | |
| 91 | .. method:: Instrument.setup(*args, **kwargs) |
| 92 | |
| 93 | This will set up the instrument on the target. Parameters this method takes |
| 94 | are particular to subclasses (see documentation for specific instruments |
| 95 | below). What actions are performed by this method are also |
| 96 | instrument-specific. Usually these will be things like installing |
| 97 | executables, starting services, deploying assets, etc. Typically, this method |
| 98 | needs to be invoked at most once per reboot of the target (unless |
| 99 | ``teardown()`` has been called), but see documentation for the instrument |
| 100 | you're interested in. |
| 101 | |
| 102 | .. method:: Instrument.reset([sites, [kinds]]) |
| 103 | |
| 104 | This is used to configure an instrument for collection. This must be invoked |
| 105 | before ``start()`` is called to begin collection. ``sites`` and ``kinds`` |
| 106 | parameters may be used to specify which channels measurements should be |
| 107 | collected from (if omitted, then measurements will be collected for all |
| 108 | available sites/kinds). This methods sets the ``active_channels`` attribute |
| 109 | of the ``Instrument``. |
| 110 | |
| 111 | .. method:: Instrument.take_measurment() |
| 112 | |
| 113 | Take a single measurement from ``active_channels``. Returns a list of |
| 114 | :class:`Measurement` objects (one for each active channel). |
| 115 | |
| 116 | .. note:: This method is only implemented by :class:`Instrument`\ s that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 117 | support ``INSTANTANEOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 118 | |
| 119 | .. method:: Instrument.start() |
| 120 | |
| 121 | Starts collecting measurements from ``active_channels``. |
| 122 | |
| 123 | .. note:: This method is only implemented by :class:`Instrument`\ s that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 124 | support ``CONTINUOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 125 | |
| 126 | .. method:: Instrument.stop() |
| 127 | |
| 128 | Stops collecting measurements from ``active_channels``. Must be called after |
| 129 | :func:`start()`. |
| 130 | |
| 131 | .. note:: This method is only implemented by :class:`Instrument`\ s that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 132 | support ``CONTINUOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 133 | |
| 134 | .. method:: Instrument.get_data(outfile) |
| 135 | |
Brendan Jackman | fc81477 | 2017-04-26 15:07:33 +0100 | [diff] [blame] | 136 | Write collected data into ``outfile``. Must be called after :func:`stop()`. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 137 | Data will be written in CSV format with a column for each channel and a row |
Brendan Jackman | fc81477 | 2017-04-26 15:07:33 +0100 | [diff] [blame] | 138 | for each sample. Column heading will be channel, labels in the form |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 139 | ``<site>_<kind>`` (see :class:`InstrumentChannel`). The order of the columns |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 140 | will be the same as the order of channels in ``Instrument.active_channels``. |
| 141 | |
Marc Bonnici | c62905c | 2017-08-18 17:22:47 +0100 | [diff] [blame] | 142 | If reporting timestamps, one channel must have a ``site`` named ``"timestamp"`` |
| 143 | and a ``kind`` of a :class:`MeasurmentType` of an appropriate time unit which will |
| 144 | be used, if appropriate, during any post processing. |
| 145 | |
| 146 | .. note:: Currently supported time units are seconds, milliseconds and |
| 147 | microseconds, other units can also be used if an appropriate |
| 148 | conversion is provided. |
| 149 | |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 150 | This returns a :class:`MeasurementCsv` instance associated with the outfile |
| 151 | that can be used to stream :class:`Measurement`\ s lists (similar to what is |
| 152 | returned by ``take_measurement()``. |
| 153 | |
| 154 | .. note:: This method is only implemented by :class:`Instrument`\ s that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 155 | support ``CONTINUOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 156 | |
Brendan Jackman | 49b547a | 2017-04-26 15:07:05 +0100 | [diff] [blame] | 157 | .. attribute:: Instrument.sample_rate_hz |
| 158 | |
| 159 | Sample rate of the instrument in Hz. Assumed to be the same for all channels. |
| 160 | |
| 161 | .. note:: This attribute is only provided by :class:`Instrument`\ s that |
Marc Bonnici | eeb5e93 | 2017-08-07 15:39:38 +0100 | [diff] [blame] | 162 | support ``CONTINUOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 163 | |
| 164 | Instrument Channel |
| 165 | ~~~~~~~~~~~~~~~~~~ |
| 166 | |
| 167 | .. class:: InstrumentChannel(name, site, measurement_type, **attrs) |
| 168 | |
| 169 | An :class:`InstrumentChannel` describes a single type of measurement that may |
| 170 | be collected by an :class:`Instrument`. A channel is primarily defined by a |
| 171 | ``site`` and a ``measurement_type``. |
| 172 | |
| 173 | A ``site`` indicates where on the target a measurement is collected from |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 174 | (e.g. a voltage rail or location of a sensor). |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 175 | |
| 176 | A ``measurement_type`` is an instance of :class:`MeasurmentType` that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 177 | describes what sort of measurement this is (power, temperature, etc). Each |
| 178 | measurement type has a standard unit it is reported in, regardless of an |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 179 | instrument used to collect it. |
| 180 | |
| 181 | A channel (i.e. site/measurement_type combination) is unique per instrument, |
| 182 | however there may be more than one channel associated with one site (e.g. for |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 183 | both voltage and power). |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 184 | |
| 185 | It should not be assumed that any site/measurement_type combination is valid. |
| 186 | The list of available channels can queried with |
| 187 | :func:`Instrument.list_channels()`. |
| 188 | |
| 189 | .. attribute:: InstrumentChannel.site |
| 190 | |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 191 | The name of the "site" from which the measurements are collected (e.g. voltage |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 192 | rail, sensor, etc). |
| 193 | |
| 194 | .. attribute:: InstrumentChannel.kind |
| 195 | |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 196 | A string indicating the type of measurement that will be collected. This is |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 197 | the ``name`` of the :class:`MeasurmentType` associated with this channel. |
| 198 | |
| 199 | .. attribute:: InstrumentChannel.units |
| 200 | |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 201 | Units in which measurement will be reported. this is determined by the |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 202 | underlying :class:`MeasurmentType`. |
| 203 | |
| 204 | .. attribute:: InstrumentChannel.label |
| 205 | |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 206 | A label that can be attached to measurements associated with with channel. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 207 | This is constructed with :: |
| 208 | |
| 209 | '{}_{}'.format(self.site, self.kind) |
| 210 | |
| 211 | |
| 212 | Measurement Types |
| 213 | ~~~~~~~~~~~~~~~~~ |
| 214 | |
| 215 | In order to make instruments easer to use, and to make it easier to swap them |
| 216 | out when necessary (e.g. change method of collecting power), a number of |
| 217 | standard measurement types are defined. This way, for example, power will always |
| 218 | be reported as "power" in Watts, and never as "pwr" in milliWatts. Currently |
| 219 | defined measurement types are |
| 220 | |
| 221 | |
Marc Bonnici | c62905c | 2017-08-18 17:22:47 +0100 | [diff] [blame] | 222 | +-------------+-------------+---------------+ |
| 223 | | name | units | category | |
| 224 | +=============+=============+===============+ |
| 225 | | time | seconds | | |
| 226 | +-------------+-------------+---------------+ |
| 227 | | time | microseconds| | |
| 228 | +-------------+-------------+---------------+ |
| 229 | | time | milliseconds| | |
| 230 | +-------------+-------------+---------------+ |
| 231 | | temperature | degrees | | |
| 232 | +-------------+-------------+---------------+ |
| 233 | | power | watts | power/energy | |
| 234 | +-------------+-------------+---------------+ |
| 235 | | voltage | volts | power/energy | |
| 236 | +-------------+-------------+---------------+ |
| 237 | | current | amps | power/energy | |
| 238 | +-------------+-------------+---------------+ |
| 239 | | energy | joules | power/energy | |
| 240 | +-------------+-------------+---------------+ |
| 241 | | tx | bytes | data transfer | |
| 242 | +-------------+-------------+---------------+ |
| 243 | | rx | bytes | data transfer | |
| 244 | +-------------+-------------+---------------+ |
| 245 | | tx/rx | bytes | data transfer | |
| 246 | +-------------+-------------+---------------+ |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 247 | |
| 248 | |
| 249 | .. instruments: |
| 250 | |
| 251 | Available Instruments |
| 252 | --------------------- |
| 253 | |
| 254 | This section lists instruments that are currently part of devlib. |
| 255 | |
| 256 | TODO |