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 |
Sergei Trofimov | 823ce71 | 2017-08-30 14:55:42 +0100 | [diff] [blame] | 68 | period of time via ``start()``, ``stop()``, ``get_data()``, |
| 69 | and (optionally) ``get_raw`` methods. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 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 | |
Brendan Jackman | 1513db0 | 2017-05-10 11:18:21 +0100 | [diff] [blame] | 102 | .. method:: Instrument.reset(sites=None, kinds=None, channels=None) |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 103 | |
| 104 | This is used to configure an instrument for collection. This must be invoked |
Brendan Jackman | 1513db0 | 2017-05-10 11:18:21 +0100 | [diff] [blame] | 105 | before ``start()`` is called to begin collection. This methods sets the |
| 106 | ``active_channels`` attribute of the ``Instrument``. |
| 107 | |
| 108 | If ``channels`` is provided, it is a list of names of channels to enable and |
| 109 | ``sites`` and ``kinds`` must both be ``None``. |
| 110 | |
| 111 | Otherwise, if one of ``sites`` or ``kinds`` is provided, all channels |
| 112 | matching the given sites or kinds are enabled. If both are provided then all |
| 113 | channels of the given kinds at the given sites are enabled. |
| 114 | |
| 115 | If none of ``sites``, ``kinds`` or ``channels`` are provided then all |
| 116 | available channels are enabled. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 117 | |
| 118 | .. method:: Instrument.take_measurment() |
| 119 | |
| 120 | Take a single measurement from ``active_channels``. Returns a list of |
| 121 | :class:`Measurement` objects (one for each active channel). |
| 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 ``INSTANTANEOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 125 | |
| 126 | .. method:: Instrument.start() |
| 127 | |
| 128 | Starts collecting measurements from ``active_channels``. |
| 129 | |
| 130 | .. note:: This method is only implemented by :class:`Instrument`\ s that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 131 | support ``CONTINUOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 132 | |
| 133 | .. method:: Instrument.stop() |
| 134 | |
| 135 | Stops collecting measurements from ``active_channels``. Must be called after |
| 136 | :func:`start()`. |
| 137 | |
| 138 | .. note:: This method is only implemented by :class:`Instrument`\ s that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 139 | support ``CONTINUOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 140 | |
| 141 | .. method:: Instrument.get_data(outfile) |
| 142 | |
Brendan Jackman | fc81477 | 2017-04-26 15:07:33 +0100 | [diff] [blame] | 143 | Write collected data into ``outfile``. Must be called after :func:`stop()`. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 144 | 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] | 145 | for each sample. Column heading will be channel, labels in the form |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 146 | ``<site>_<kind>`` (see :class:`InstrumentChannel`). The order of the columns |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 147 | will be the same as the order of channels in ``Instrument.active_channels``. |
| 148 | |
Marc Bonnici | c62905c | 2017-08-18 17:22:47 +0100 | [diff] [blame] | 149 | If reporting timestamps, one channel must have a ``site`` named ``"timestamp"`` |
| 150 | and a ``kind`` of a :class:`MeasurmentType` of an appropriate time unit which will |
| 151 | be used, if appropriate, during any post processing. |
| 152 | |
| 153 | .. note:: Currently supported time units are seconds, milliseconds and |
| 154 | microseconds, other units can also be used if an appropriate |
| 155 | conversion is provided. |
| 156 | |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 157 | This returns a :class:`MeasurementCsv` instance associated with the outfile |
| 158 | that can be used to stream :class:`Measurement`\ s lists (similar to what is |
| 159 | returned by ``take_measurement()``. |
| 160 | |
| 161 | .. note:: This method is only implemented by :class:`Instrument`\ s that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 162 | support ``CONTINUOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 163 | |
Sergei Trofimov | 823ce71 | 2017-08-30 14:55:42 +0100 | [diff] [blame] | 164 | .. method:: Instrument.get_raw() |
| 165 | |
| 166 | Returns a list of paths to files containing raw output from the underlying |
| 167 | source(s) that is used to produce the data CSV. If now raw output is |
| 168 | generated or saved, an empty list will be returned. The format of the |
| 169 | contents of the raw files is entirely source-dependent. |
| 170 | |
Brendan Jackman | 49b547a | 2017-04-26 15:07:05 +0100 | [diff] [blame] | 171 | .. attribute:: Instrument.sample_rate_hz |
| 172 | |
| 173 | Sample rate of the instrument in Hz. Assumed to be the same for all channels. |
| 174 | |
| 175 | .. note:: This attribute is only provided by :class:`Instrument`\ s that |
Marc Bonnici | eeb5e93 | 2017-08-07 15:39:38 +0100 | [diff] [blame] | 176 | support ``CONTINUOUS`` measurement. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 177 | |
| 178 | Instrument Channel |
| 179 | ~~~~~~~~~~~~~~~~~~ |
| 180 | |
| 181 | .. class:: InstrumentChannel(name, site, measurement_type, **attrs) |
| 182 | |
| 183 | An :class:`InstrumentChannel` describes a single type of measurement that may |
| 184 | be collected by an :class:`Instrument`. A channel is primarily defined by a |
| 185 | ``site`` and a ``measurement_type``. |
| 186 | |
| 187 | A ``site`` indicates where on the target a measurement is collected from |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 188 | (e.g. a voltage rail or location of a sensor). |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 189 | |
| 190 | A ``measurement_type`` is an instance of :class:`MeasurmentType` that |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 191 | describes what sort of measurement this is (power, temperature, etc). Each |
| 192 | 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] | 193 | instrument used to collect it. |
| 194 | |
| 195 | A channel (i.e. site/measurement_type combination) is unique per instrument, |
| 196 | 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] | 197 | both voltage and power). |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 198 | |
| 199 | It should not be assumed that any site/measurement_type combination is valid. |
| 200 | The list of available channels can queried with |
| 201 | :func:`Instrument.list_channels()`. |
| 202 | |
| 203 | .. attribute:: InstrumentChannel.site |
| 204 | |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 205 | 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] | 206 | rail, sensor, etc). |
| 207 | |
| 208 | .. attribute:: InstrumentChannel.kind |
| 209 | |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 210 | 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] | 211 | the ``name`` of the :class:`MeasurmentType` associated with this channel. |
| 212 | |
| 213 | .. attribute:: InstrumentChannel.units |
| 214 | |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 215 | Units in which measurement will be reported. this is determined by the |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 216 | underlying :class:`MeasurmentType`. |
| 217 | |
| 218 | .. attribute:: InstrumentChannel.label |
| 219 | |
Marc Bonnici | 1fd5636 | 2017-01-10 15:35:21 +0000 | [diff] [blame] | 220 | A label that can be attached to measurements associated with with channel. |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 221 | This is constructed with :: |
| 222 | |
| 223 | '{}_{}'.format(self.site, self.kind) |
| 224 | |
| 225 | |
| 226 | Measurement Types |
| 227 | ~~~~~~~~~~~~~~~~~ |
| 228 | |
| 229 | In order to make instruments easer to use, and to make it easier to swap them |
| 230 | out when necessary (e.g. change method of collecting power), a number of |
| 231 | standard measurement types are defined. This way, for example, power will always |
| 232 | be reported as "power" in Watts, and never as "pwr" in milliWatts. Currently |
| 233 | defined measurement types are |
| 234 | |
| 235 | |
Marc Bonnici | c62905c | 2017-08-18 17:22:47 +0100 | [diff] [blame] | 236 | +-------------+-------------+---------------+ |
| 237 | | name | units | category | |
| 238 | +=============+=============+===============+ |
Sergei Trofimov | 01b5cff | 2017-09-07 14:26:04 +0100 | [diff] [blame] | 239 | | count | count | | |
| 240 | +-------------+-------------+---------------+ |
| 241 | | percent | percent | | |
Marc Bonnici | c62905c | 2017-08-18 17:22:47 +0100 | [diff] [blame] | 242 | +-------------+-------------+---------------+ |
Sergei Trofimov | 2afa8f8 | 2017-08-30 14:27:03 +0100 | [diff] [blame] | 243 | | time_us | microseconds| time | |
Marc Bonnici | c62905c | 2017-08-18 17:22:47 +0100 | [diff] [blame] | 244 | +-------------+-------------+---------------+ |
Sergei Trofimov | 2afa8f8 | 2017-08-30 14:27:03 +0100 | [diff] [blame] | 245 | | time_ms | milliseconds| time | |
Marc Bonnici | c62905c | 2017-08-18 17:22:47 +0100 | [diff] [blame] | 246 | +-------------+-------------+---------------+ |
Sergei Trofimov | 01b5cff | 2017-09-07 14:26:04 +0100 | [diff] [blame] | 247 | | temperature | degrees | thermal | |
Marc Bonnici | c62905c | 2017-08-18 17:22:47 +0100 | [diff] [blame] | 248 | +-------------+-------------+---------------+ |
| 249 | | power | watts | power/energy | |
| 250 | +-------------+-------------+---------------+ |
| 251 | | voltage | volts | power/energy | |
| 252 | +-------------+-------------+---------------+ |
| 253 | | current | amps | power/energy | |
| 254 | +-------------+-------------+---------------+ |
| 255 | | energy | joules | power/energy | |
| 256 | +-------------+-------------+---------------+ |
| 257 | | tx | bytes | data transfer | |
| 258 | +-------------+-------------+---------------+ |
| 259 | | rx | bytes | data transfer | |
| 260 | +-------------+-------------+---------------+ |
| 261 | | tx/rx | bytes | data transfer | |
| 262 | +-------------+-------------+---------------+ |
Sergei Trofimov | 4e6afe9 | 2015-10-09 09:30:04 +0100 | [diff] [blame] | 263 | |
| 264 | |
| 265 | .. instruments: |
| 266 | |
| 267 | Available Instruments |
| 268 | --------------------- |
| 269 | |
| 270 | This section lists instruments that are currently part of devlib. |
| 271 | |
| 272 | TODO |