OLD | NEW |
---|---|
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Interface for a USB-connected Monsoon power meter. | 5 """Interface for a USB-connected Monsoon power meter. |
6 | 6 |
7 http://msoon.com/LabEquipment/PowerMonitor/ | 7 http://msoon.com/LabEquipment/PowerMonitor/ |
8 Currently Unix-only. Relies on fcntl, /dev, and /tmp. | 8 Currently Unix-only. Relies on fcntl, /dev, and /tmp. |
9 """ | 9 """ |
10 | 10 |
11 import collections | 11 import collections |
12 import logging | 12 import logging |
13 import os | 13 import os |
14 import select | 14 import select |
15 import struct | 15 import struct |
16 import time | 16 import time |
17 | 17 |
18 from telemetry.core import util | 18 from telemetry.core import util |
19 | 19 |
20 util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'pyserial') | 20 util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'pyserial') |
21 import serial # pylint: disable=F0401 | 21 import serial # pylint: disable=F0401 |
22 import serial.tools.list_ports | |
22 | 23 |
23 | 24 |
24 Power = collections.namedtuple('Power', ['amps', 'volts']) | 25 Power = collections.namedtuple('Power', ['amps', 'volts']) |
25 | 26 |
26 | 27 |
27 class Monsoon: | 28 class Monsoon: |
28 """Provides a simple class to use the power meter. | 29 """Provides a simple class to use the power meter. |
29 | 30 |
30 mon = monsoon.Monsoon() | 31 mon = monsoon.Monsoon() |
31 mon.SetVoltage(3.7) | 32 mon.SetVoltage(3.7) |
(...skipping 15 matching lines...) Expand all Loading... | |
47 | 48 |
48 self._coarse_ref = self._fine_ref = self._coarse_zero = self._fine_zero = 0 | 49 self._coarse_ref = self._fine_ref = self._coarse_zero = self._fine_zero = 0 |
49 self._coarse_scale = self._fine_scale = 0 | 50 self._coarse_scale = self._fine_scale = 0 |
50 self._last_seq = 0 | 51 self._last_seq = 0 |
51 self._voltage_multiplier = None | 52 self._voltage_multiplier = None |
52 | 53 |
53 if device: | 54 if device: |
54 self.ser = serial.Serial(device, timeout=1) | 55 self.ser = serial.Serial(device, timeout=1) |
55 return | 56 return |
56 | 57 |
57 while 1: # Try all /dev/ttyACM* until we find one we can use. | 58 while 1: |
58 for dev in os.listdir('/dev'): | 59 devices = serial.tools.list_ports.comports() |
59 if not dev.startswith('ttyACM'): | 60 for dev in devices: |
tonyg
2014/06/09 16:51:56
This loop'd be a lot more readable as
for port, d
| |
61 if not dev[1].lower().startswith('mobile device power monitor'): | |
60 continue | 62 continue |
61 tmpname = '/tmp/monsoon.%s.%s' % (os.uname()[0], dev) | 63 tmpname = '/tmp/monsoon.%s.%s' % (os.uname()[0], os.path.basename(dev[0] )) |
tonyg
2014/06/09 16:51:57
nit: please hold line length to 80 cols.
http://g
| |
62 self._tempfile = open(tmpname, 'w') | 64 self._tempfile = open(tmpname, 'w') |
63 try: # Use a lockfile to ensure exclusive access. | 65 try: # Use a lockfile to ensure exclusive access. |
64 # Put the import in here to avoid doing it on unsupported platforms. | 66 # Put the import in here to avoid doing it on unsupported platforms. |
65 import fcntl | 67 import fcntl |
66 fcntl.lockf(self._tempfile, fcntl.LOCK_EX | fcntl.LOCK_NB) | 68 fcntl.lockf(self._tempfile, fcntl.LOCK_EX | fcntl.LOCK_NB) |
67 except IOError: | 69 except IOError: |
68 logging.error('device %s is in use', dev) | 70 logging.error('device %s is in use', dev) |
69 continue | 71 continue |
70 | 72 |
71 try: # Try to open the device. | 73 try: # Try to open the device. |
72 self.ser = serial.Serial('/dev/%s' % dev, timeout=1) | 74 self.ser = serial.Serial(dev[0], timeout=1) |
73 self.StopDataCollection() # Just in case. | 75 self.StopDataCollection() # Just in case. |
74 self._FlushInput() # Discard stale input. | 76 self._FlushInput() # Discard stale input. |
75 status = self.GetStatus() | 77 status = self.GetStatus() |
76 except IOError, e: | 78 except IOError, e: |
77 logging.error('error opening device %s: %s', dev, e) | 79 logging.error('error opening device %s: %s', dev, e) |
78 continue | 80 continue |
79 | 81 |
80 if not status: | 82 if not status: |
81 logging.error('no response from device %s', dev) | 83 logging.error('no response from device %s', dev) |
82 elif serialno and status['serialNumber'] != serialno: | 84 elif serialno and status['serialNumber'] != serialno: |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 logging.error('exception from serial port') | 278 logging.error('exception from serial port') |
277 return None | 279 return None |
278 elif len(ready_r) > 0: | 280 elif len(ready_r) > 0: |
279 flushed += 1 | 281 flushed += 1 |
280 self.ser.read(1) # This may cause underlying buffering. | 282 self.ser.read(1) # This may cause underlying buffering. |
281 self.ser.flush() # Flush the underlying buffer too. | 283 self.ser.flush() # Flush the underlying buffer too. |
282 else: | 284 else: |
283 break | 285 break |
284 if flushed > 0: | 286 if flushed > 0: |
285 logging.debug('dropped >%d bytes', flushed) | 287 logging.debug('dropped >%d bytes', flushed) |
OLD | NEW |