1# Copyright 2015 The Chromium OS 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 5import error, logging, os, serial, shutil, threading, time 6 7_power_play_data_file = '/tmp/power_play_data' 8 9class PowerPlay(object): 10 """Class to record serial over USB data from Power Play (go/powerplay). 11 12 It detects if powerplay is connected to the DUT over USB and opens the 13 serial port to start receiving powerplay data. It also opens a text file to 14 save this data after some formatting. 15 """ 16 17 version = 1 18 19 def __init__(self, test_obj, record_interval=0): 20 """Initialize PowerPlay. 21 22 @param test_obj: test object. 23 @param record_interval: Power play data recording interval in seconds. 24 """ 25 self.test = test_obj 26 self.ser = None 27 self.recording_interval = record_interval 28 self.momentary_curr_list = list() 29 self.record_thread = None 30 31 def extract_current(self, pp_data): 32 """Extract momentary current value from each line of powerplay data. 33 34 @param pp_data: Single line of powerplay data with eight comma separated 35 values. 36 @return list containing momentary current values. 37 """ 38 if pp_data[0].isdigit(): 39 self.momentary_curr_list.append(float(pp_data[pp_data.index(',')+1:] 40 [:pp_data[pp_data.index(',')+1:].index(',')])) 41 return self.momentary_curr_list 42 43 def start_recording_power_play_data(self): 44 """Starts a new thread to record power play data.""" 45 self.record_thread = threading.Thread(target=self.start_record_thread) 46 self.record_thread.daemon = True 47 self.record_thread.start() 48 49 def start_record_thread(self): 50 """Start recording power play data. 51 52 Get a list of connected USB devices and try to establish a serial 53 connection. Once the connection is established, open a text file and 54 start reading serial data and write it to the text file after some 55 formatting. 56 """ 57 devices = [x for x in os.listdir('/dev/') if x.startswith('ttyUSB')] 58 59 for device in devices: 60 device_link = '/dev/' + device 61 try: 62 if self.ser == None: 63 logging.info('Trying ... %s', device_link) 64 self.ser = serial.Serial(device_link, 115200) 65 logging.info('Successfully connected to %s', device_link) 66 break 67 except serial.SerialException, e: 68 raise error.TestError('Failed to connect to %s becuase of %s' % 69 (device_link, str(e))) 70 71 self.text_file = open(_power_play_data_file, 'w') 72 73 if self.ser != None: 74 title_row = ('time,powerplay_timestamp,momentary_current (A),' + 75 'momentary_charge (AH),average_current (A),' + 76 'total_standby_time,total_wake_time,num_wakes,is_awake?\n') 77 self.text_file.write(title_row) 78 start_time = time.time() 79 while self.ser.readline(): 80 current_timestamp = (('{:>10.3f}'. 81 format(time.time() - start_time)).replace(' ', '')) 82 pp_data = (self.ser.readline().replace('\00', ''). 83 replace(' ', ',').replace('\r', '')) 84 if (not pp_data.startswith('#') and (len(pp_data) > 30) and 85 not self.text_file.closed): 86 self.text_file.write(current_timestamp + ',' + pp_data) 87 self.momentary_curr_list = self.extract_current(pp_data) 88 time.sleep(self.recording_interval) 89 self.ser.flushInput() 90 else: 91 self.text_file.write('No data from powerplay. Check connection.') 92 93 def stop_recording_power_play_data(self): 94 """Stop recording power play data. 95 96 Close the text file and copy it to the test log results directory. Also 97 report current data to the performance dashboard. 98 """ 99 if not self.text_file.closed: 100 self.text_file.close() 101 shutil.copy(_power_play_data_file, self.test.resultsdir) 102 self.test.output_perf_value(description='momentary_current_draw', 103 value=self.momentary_curr_list, 104 units='Amps', higher_is_better=False) 105