Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: common/monsoon/monsoon/monsoon_wrapper.py

Issue 3018533002: Implementing a Monsoon power monitor trace agent, utilizing the UI infrastructure that the BattOr a…
Patch Set: Updating static methods and fixing test fakes. Created 3 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import atexit
6 import py_utils
7 import re
8 import subprocess
9 import tempfile
10
11 USB_PASSTHROUGH_OFF = "off"
12 USB_PASSTHROUGH_ON = "on"
13 USB_PASSTHROUGH_AUTO = "auto"
14
15 UsbModes = [USB_PASSTHROUGH_OFF, USB_PASSTHROUGH_ON, USB_PASSTHROUGH_AUTO]
16
17 class MonsoonWrapper(object):
18 def __init__(self, script):
19 self.script = script
20 self._process = None
21 # Register atexit handler to kill any monsoon processes in the case of
22 # abnormal program termination.
23 atexit.register(self.TerminateMonsoonProcess)
24
25 def ReadStatusProperties(self):
26 """ Reads status properties from Monsoon, returning a dictionary of
27 properties.
28 """
29 status_text = self.ExecuteBlocking(["--status"])
30 status = {}
31 for status_line in status_text:
32 # Sometimes transient USB serial errors are reported. Just ignore them
33 # and only use strings with : in them.
34 if ":" in status_line:
35 key, value = status_line.split(':')
36 status[key] = value
37 return status
38
39 def EnableUSB(self):
40 """ Shorthand for SetUSBMode(USB_PASSTHROUGH_ON) """
41 self.SetUSBMode(USB_PASSTHROUGH_ON)
42
43 def DisableUSB(self):
44 """ Shorthand for SetUSBMode(USB_PASSTHROUGH_OFF) """
45 self.SetUSBMode(USB_PASSTHROUGH_OFF)
46
47 def SetUSBMode(self, mode):
48 """ Set the Monsoon USB mode.
49 """
50 if mode not in UsbModes: raise Exception("Invalid USB mode " + mode)
51 # Sometimes Monsoon fails to make USB passthrough mode changes
52 # permanent if there are transient USB serial errors.
53 retry_count = 5
54 while self.GetUSBMode() is not mode:
55 self.ExecuteBlocking(["--usbpassthrough", mode])
56 if retry_count is 0: Exception("Failed to set USB mode!")
57 retry_count -= 1
58
59 def GetUSBMode(self):
60 """ Retrieves the current Monsoon USB mode, returning USB_PASSTHROUGH_OFF
61 if the status could not be retrieved.
62 """
63 properties = self.ReadStatusProperties()
64 if "usbPassthroughMode" in properties:
65 return UsbModes[int(properties["usbPassthroughMode"])]
66 return USB_PASSTHROUGH_OFF
67
68 def ReadPower(self, time, frequency):
69 """ Reads power from the Monsoon device over a specified perdiod while
70 blocking, returning a file containing raw monsoon data. """
71 sample_count = time * frequency
72 args = ["--samples", str(sample_count), "--hz", str(frequency),
73 "--timestamp"]
74 return self.ExecuteBlocking(args)
75
76 def ExecuteBlocking(self, args):
77 """ Executes a blocking operation on the Monsoon device, returning a file
78 containing stdout output. """
79 if self.IsProcessRunning():
80 raise Exception("Monsoon subprocess already running!")
81 result_file = tempfile.TemporaryFile()
82 subprocess.check_call([self.script] + args, stdout=result_file)
83 result_file.seek(0)
84 return result_file
85
86 def BeginReadPower(self, frequency, out=subprocess.PIPE):
87 """ Begins a non-blocking read of power from the Monsoon device, returning
88 the stdout file of the subprocess.
89 """
90 args = ["--samples", "-1", "--hz", str(frequency), "--timestamp"]
91 return self.BeginExecution(args=args, out=out)
92
93 def BeginExecution(self, args = [], out=subprocess.PIPE):
94 """ Begins a non-blocking operation on the Monsoon device, returning the
95 stdout file of the subprocess.
96 """
97 if self.IsProcessRunning():
98 raise Exception("Monsoon subprocess already running!")
99 self._process = subprocess.Popen([self.script] + args, stdout=out)
100 return self._process.stdout
101
102 def EndExecution(self):
103 """ Ends non-blocking execution of the Monsoon subprocess, returning the
104 stdout file of the subprocess. """
105 if self._process is None or self._process.poll() is not None:
106 raise Exception("Monsoon subprocess not running when going to end "
107 + "execution.")
108 self._process.terminate()
109 self._process.wait()
110 result_file = self._process.stdout
111 self._process = None
112 self._result_file = None
113 return result_file
114
115 def IsProcessRunning(self):
116 """ Returns whether or not the Monsoon subprocess is running.
117 """
118 return self._process is not None and self._process.poll() is None
119
120 def TerminateMonsoonProcess(self):
121 """ Terminates the Monsoon subprocess if it is running.
122 """
123 if self._process is not None and self._process.poll() is None:
124 self._process.kill()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698