Skip to content

Commit 4854f38

Browse files
committed
Add a convertor, from our output to UEMonitor compatible format
1 parent adee58c commit 4854f38

File tree

7 files changed

+250
-52
lines changed

7 files changed

+250
-52
lines changed

CurrentPlottingModule/CurrentLivePlotter.py

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import multiprocessing
22
import time
3+
import Monsoon.HVPM as HVPM
4+
import Monsoon.sampleEngine as sampleEngine
5+
import Monsoon.Operations as op
36
from PyQt5 import QtGui, QtCore
47
from PyQt5.QtCore import Qt
58
from PyQt5.QtGui import QLinearGradient, QColor, QFont
@@ -21,7 +24,6 @@ def __init__(self, file_io, parent=None):
2124
self.file_data = []
2225
self.data = []
2326
self.time_data = []
24-
2527
self.idx = 0
2628
self.groupbox_stylesheet = 'QGroupBox {font-size: 16px;' \
2729
'font-weight: bold;} ' \
@@ -102,37 +104,39 @@ def init_plot(self):
102104
# pg.mkPen('w', width=100, style=QtCore.Qt.DashLine)
103105
self.w1.setBackground(QColor(10, 50, 80))
104106

105-
def update_data(self,sample):
106-
if sample and self.is_start:
107-
self.temp_data = sample
108-
if len(self.data) > 5000:
109-
self.data[:-1] = self.data[1:] # shift data left
110-
self.data[-1] = self.temp_data
111-
self.time_data[:-1] = self.time_data[1:]
112-
self.time_data[-1] = self.idx
113-
else:
114-
self.data.append(self.temp_data)
115-
self.time_data.append(self.idx)
116-
self.p.setData(x=self.time_data , y=self.data)
117-
self.w1.setRange(xRange=[self.idx - 2000, self.idx + 50])
118-
self.usb_panel.display(self.temp_data)
119-
# Write to file.
120-
# FIXME: File IO bookmark
121-
self.file_io.write_power_monitor_current([time.time(), '{0:.4f}'.format(self.temp_data)])
122-
self.idx += 1
107+
### Please do not delete this part of codes
108+
#def update_data(self, sample):
109+
# if sample and self.is_start:
110+
# self.temp_data = sample
111+
# if len(self.data) > 5000:
112+
# self.data[:-1] = self.data[1:] # shift data left
113+
# self.data[-1] = self.temp_data
114+
# self.time_data[:-1] = self.time_data[1:]
115+
# self.time_data[-1] = self.idx
116+
# else:
117+
# self.data.append(self.temp_data)
118+
# self.time_data.append(self.idx)
119+
# self.p.setData(x=self.time_data , y=self.data)
120+
# self.w1.setRange(xRange=[self.idx - 2000, self.idx + 50])
121+
# self.usb_panel.display(self.temp_data)
122+
# # Write to file.
123+
# # FIXME: File IO bookmark
124+
# self.file_io.write_power_monitor_current([time.time(), '{0:.4f}'.format(self.temp_data)])
125+
# self.idx += 1
123126

124127
def start_monitor(self):
125128
self.Start_btn.setDisabled(True)
126129
self.Stop_btn.setEnabled(True)
127-
if self.is_start == False:
128-
self.is_start = True
130+
if self.power_monitor == None:
131+
self.power_monitor = PowerMonitorHandler(self.p, self.w1, self.file_io, self.usb_panel)
132+
if self.power_monitor.is_start == False:
133+
self.power_monitor.is_start = True
134+
self.power_monitor.start()
129135
else:
130-
self.power_monitor = PowerMonitorHandler()
131-
self.power_monitor.samp_trigger.connect(self.update_data)
132136
self.power_monitor.start()
133137

134-
135138
def stop_monitor(self):
136-
self.is_start = False
139+
#self.power_monitor.engine.monsoon.stopSampling()
140+
self.power_monitor.is_start = False
137141
self.Stop_btn.setDisabled(True)
138-
self.Start_btn.setEnabled(True)
142+
self.Start_btn.setEnabled(True)
Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import threading
2+
import time
3+
24
import Monsoon.HVPM as HVPM
35
import Monsoon.sampleEngine as sampleEngine
46
import Monsoon.Operations as op
@@ -7,25 +9,67 @@
79
# TODO: 20190327 inherit the sampleEngine class and re-implement the relevant parts.
810

911
class PowerMonitorHandler(QThread):
10-
samp_trigger = pyqtSignal(float)
11-
def __init__(self):
12+
def __init__(self, plot, plot_win, file_IO, USB_PANEL):
13+
self.p = plot
14+
self.w1 = plot_win
15+
self.file_io = file_IO
16+
self.data = []
17+
self.time_data = []
18+
self.temp_data = 0
19+
self.idx = 0
20+
self.is_start = True
21+
self.usb_panel = USB_PANEL
1222
super(PowerMonitorHandler, self).__init__()
13-
# super(PowerMonitorHandler, self).__init__()
14-
def run(self):
15-
Mon = HVPM.Monsoon()
16-
Mon.setup_usb()
17-
Mon.setVout(4.0)
18-
self.engine = sampleEngine.SampleEngine(Mon)
19-
self.engine.signal_samp_trigger.connect(self.pass_through)
23+
self.Mon = HVPM.Monsoon()
24+
self.Mon.setup_usb()
25+
self.Mon.setVout(4.0)
26+
self.engine = sampleEngine.SampleEngine(self.Mon)
27+
self.engine.signal_samp_trigger.connect(self.pass_through2)
2028
self.engine.enableChannel(sampleEngine.channels.USBCurrent)
21-
Mon.setUSBPassthroughMode(op.USB_Passthrough.On)
29+
self.Mon.setUSBPassthroughMode(op.USB_Passthrough.On)
2230
self.engine.disableCSVOutput()
23-
#self.engine.enableCSVOutput('full_powwer_monitor_records.txt')
2431
self.engine.ConsoleOutput(False)
2532
self.numSamples = sampleEngine.triggers.SAMPLECOUNT_INFINITE
26-
self.engine.startSampling(self.numSamples) ##start sampling
27-
def pass_through(self, sample):
28-
self.samp_trigger.emit(sample)
2933

34+
def run(self):
35+
self.engine.startSampling(self.numSamples) ##start sampling
36+
37+
def pass_through2(self, sample):
38+
if sample and self.is_start:
39+
self.temp_data = sample
40+
if len(self.data) > 5000:
41+
self.data[:-1] = self.data[1:] # shift data left
42+
self.data[-1] = self.temp_data
43+
self.time_data[:-1] = self.time_data[1:]
44+
self.time_data[-1] = self.idx
45+
else:
46+
self.data.append(self.temp_data)
47+
self.time_data.append(self.idx)
48+
if sample >55:
49+
self.p.setData(x=self.time_data, y=self.data)
50+
self.w1.setRange(xRange=[self.idx - 2000, self.idx + 50])
51+
self.usb_panel.display(self.temp_data)
52+
# Write to file.
53+
# FIXME: File IO bookmark
54+
self.file_io.write_power_monitor_current([time.time(), '{0:.4f}'.format(self.temp_data)])
55+
self.idx += 1
3056

57+
def pass_through(self, sample):
58+
if sample and self.is_start:
59+
self.temp_data = sample
60+
if len(self.data) > 5000:
61+
self.data[:-1] = self.data[1:] # shift data left
62+
self.data[-1] = self.temp_data
63+
self.time_data[:-1] = self.time_data[1:]
64+
self.time_data[-1] = self.idx
65+
else:
66+
self.data.append(self.temp_data)
67+
self.time_data.append(self.idx)
3168

69+
self.p.setData(x=self.time_data , y=self.data)
70+
self.w1.setRange(xRange=[self.idx - 2000, self.idx + 50])
71+
self.usb_panel.display(self.temp_data)
72+
# Write to file.
73+
# FIXME: File IO bookmark
74+
self.file_io.write_power_monitor_current([time.time(), '{0:.4f}'.format(self.temp_data)])
75+
self.idx += 1

LogDecoderTabview.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ def create_pyqtgraph_rsrp_snr_plotter(self):
594594
rsrp_snr_layout = QVBoxLayout()
595595
self.rsrp_win = pg.PlotWidget()
596596
self.snr_win = pg.PlotWidget()
597+
597598
self.init_rsrp_snr_plot()
598599

599600
rsrp_snr_layout.addWidget(self.rsrp_win)
@@ -1125,7 +1126,7 @@ def add_tool_tips(self):
11251126
'unless start the logging again.')
11261127

11271128
# The following tooltips are for elements in ConfigurationEditor
1128-
self.config_editor_dlg.add_tool_tips_dlg()
1129+
# self.config_editor_dlg.add_tool_tips_dlg()
11291130

11301131
# Multithread signal processing
11311132
# # Fetch updated configs from Configuration Editor
@@ -1194,15 +1195,23 @@ def dbg_fetch_rsrp_snr(self):
11941195

11951196
# print(measurement_dict)
11961197
self.decoder.rsrp_snr_buf = {'ts': [], 'RSRP': [], 'SNR': []} # reset the buf
1197-
self.samptime += [x - self.decoder.start_timestamp for x in measurement_dict['ts']]
1198-
self.rsrp_data += [float(x)/10 for x in measurement_dict['RSRP']]
1199-
self.snr_data += [float(x)/10 for x in measurement_dict['SNR']]
1200-
1201-
# FIXME: RSRP SNR writer.
1202-
self.file_io.write_rsrp_snr([measurement_dict['ts'], measurement_dict['RSRP'],
1203-
measurement_dict['SNR']])
1204-
1205-
self.update_rsrp_snr_plot()
1198+
#self.samptime += [x - self.decoder.start_timestamp for x in measurement_dict['ts']]
1199+
if measurement_dict['ts'] == []:
1200+
return
1201+
else:
1202+
if -1500 < float(measurement_dict['RSRP'][0]) < 0 and -200 < float(measurement_dict['SNR'][0]) < 250:
1203+
self.samptime.append(measurement_dict['ts'][0] - self.decoder.start_timestamp)
1204+
self.rsrp_data.append(float(measurement_dict['RSRP'][0])/10)
1205+
self.snr_data .append(float(measurement_dict['SNR'][0]) / 10)
1206+
else:
1207+
return
1208+
# self.rsrp_data += [float(x)/10 for x in measurement_dict['RSRP']]
1209+
# self.snr_data += [float(x)/10 for x in measurement_dict['SNR']]
1210+
# FIXME: RSRP SNR writer.
1211+
self.file_io.write_rsrp_snr([measurement_dict['ts'][0], int(measurement_dict['RSRP'][0]),
1212+
int(measurement_dict['SNR'][0])])
1213+
1214+
self.update_rsrp_snr_plot()
12061215

12071216
def update_rsrp_snr_plot(self):
12081217
# self.prt += 2

LogDecoders.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,10 @@ def hex_to_ascii(self, byte_list):
114114
for b_ascii in byte_list:
115115
if b_ascii != '00' or int(b_ascii, 16) < 127:
116116
byte_str += b_ascii
117-
return bytearray.fromhex(byte_str).decode()
118-
117+
try:
118+
return bytearray.fromhex(byte_str).decode()
119+
except UnicodeDecodeError:
120+
return ''
119121
def parse_one_msg_common(self, data_flow):
120122
result_list = []
121123
if len(data_flow) < 8:
@@ -542,6 +544,7 @@ def run(self):
542544
parsed_msg = ''
543545
time_stamp = .0
544546
payload_len = 1
547+
max_len = 0
545548
app_rep_flag = False
546549

547550
empty_msg_list = [0, 0, .0] # Order: seq_num, timestamp, time tick,
@@ -607,6 +610,13 @@ def run(self):
607610
for i in range(2):
608611
str_buf.append(self.read_byte(1))
609612
payload_len = self.hex_to_decimal(str_buf)
613+
# if max_len < payload_len:
614+
# max_len = payload_len
615+
# print('[INFO]Max payload length:', max_len)
616+
if payload_len > 720:
617+
st = states['UNKNOWN']
618+
print('[ERROR] Found unbounded large payload length.')
619+
continue
610620
st = states['DATA']
611621
elif st == states['DATA']:
612622
str_buf = []

RawLogFormatConvertor.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
"""
2+
Convert the raw log expoerted by our Quectel Debug Log Decoder to UELogViewer compatible format,
3+
so that one can import it into the UELogViewer or UEMonitor.
4+
Created: 2019-04-01
5+
"""
6+
import csv
7+
import os
8+
import time
9+
from utils import get_file_list
10+
11+
class RawLogFormatConvertor(object):
12+
13+
def __init__(self):
14+
self.abs_work_dir = os.getcwd()
15+
self.output_dir = self.abs_work_dir + '/output_files/'
16+
self.dir_list = []
17+
self.prepare_dirs()
18+
19+
def prepare_dirs(self):
20+
temp_list = os.listdir(self.output_dir)
21+
self.dir_list = [x for x in temp_list if '.' not in x] # exclude the normal files
22+
# self.dir_list.sort()
23+
# print(self.dir_list)
24+
25+
def convert_one_raw_file(self, folder_name):
26+
print('Project name:', folder_name)
27+
raw_log_file_name = self.output_dir + folder_name + '/debug_log_raw.txt'
28+
if os.path.exists(raw_log_file_name):
29+
debug_log_raw_uem = self.output_dir + folder_name + '/debug_log_raw_uem.txt' # export_file
30+
if os.path.exists(debug_log_raw_uem):
31+
print('Already exported. Pass.')
32+
return False # overwrite the existing UEM.txt files
33+
# The converted file does not exists, working on it.
34+
raw_log_file = open(raw_log_file_name, 'r')
35+
with open(debug_log_raw_uem, 'w', newline='') as f_out:
36+
for line in raw_log_file:
37+
if len(line) > 2000:
38+
print('Abnormal line', line[:100])
39+
continue
40+
line_buf = line.split(',')
41+
# Assume it is UTC+8 time zone. Change accordingly
42+
seq_num = line_buf[0]
43+
seq_num_str = self.int_to_hex_bytes(int(seq_num))
44+
# print(seq_num_str)
45+
try:
46+
second_frac = float(line_buf[1].split('.')[0])
47+
except TypeError:
48+
print('Not a time stamp.')
49+
continue
50+
if second_frac < 1500000000:
51+
print('Error, continue')
52+
continue
53+
millisecond_frac = line_buf[1].split('.')[1]
54+
time_stamp = time.strftime(';%Y-%m-%dT%H:%M:%S', time.localtime(float(second_frac)))
55+
time_stamp += '.{0:.7s}+08:00;'.format(millisecond_frac) # Assume it is UTC+8 time zone. Change accordingly
56+
time_tick_hex = line_buf[2]
57+
time_tick_str = self.int_to_hex_bytes(int(time_tick_hex))
58+
# msg = time_stamp + line_buf[3]
59+
byte_list = line_buf[3]
60+
if byte_list == 'APPLICATION_REPORT':
61+
byte_list = line_buf[4]
62+
byte_list = '00-00-A0-7F-00-00-' + self.process_app_rep_log(byte_list)
63+
# '00-00-A0-7F-00-00' is for APPLICATION_REPORT
64+
f_out.write(time_stamp + time_tick_str + seq_num_str + byte_list)
65+
f_out.flush()
66+
f_out.close()
67+
raw_log_file.close()
68+
return True
69+
else:
70+
return False
71+
72+
def process_app_rep_log(self, byte_list):
73+
byte_count = (len(byte_list) + 1)//3
74+
byte_count_hex = hex(byte_count)[2:].upper()
75+
prepend = ''
76+
if len(byte_count_hex) == 1:
77+
prepend = '0' + byte_count_hex + '-00-'
78+
elif len(byte_count_hex) == 2:
79+
prepend = byte_count_hex + '-00-'
80+
elif len(byte_count_hex) == 3:
81+
prepend = byte_count_hex[1:] + '-0' + byte_count_hex[1] + '-'
82+
else:
83+
print('[WARN] abnormal application report length.')
84+
return prepend + byte_list
85+
86+
def int_to_hex_bytes(self, int_input):
87+
x = hex(int_input)[2:]
88+
# print(x)
89+
byte_list = []
90+
for i in range(len(x)//2):
91+
byte_list.append(x[-2:].upper())
92+
x = x[:-2] # remove the tail bytes
93+
if len(x) == 1:
94+
byte_list.append('0' + x)
95+
# else:
96+
# byte_list.append(x)
97+
# print(byte_list)
98+
while len(byte_list) < 4:
99+
byte_list.append('00')
100+
str_msg = ''
101+
for b in byte_list:
102+
str_msg += b + '-'
103+
# print(tick_msg)
104+
return str_msg
105+
106+
def convert_all_files(self):
107+
success_list = []
108+
for dir in self.dir_list:
109+
if self.convert_one_raw_file(dir) == 1:
110+
success_list.append(dir)
111+
print('Successfully convert the raw log in these folders:', success_list)
112+
print('# of converted files:', len(success_list))
113+
114+
115+
if __name__ == '__main__':
116+
my_rlfc = RawLogFormatConvertor()
117+
# my_rlfc.convert_one_raw_file('190329_233635')
118+
my_rlfc.convert_all_files()
119+

SupportingWindows.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def __init__(self, parent=None):
2222
self.height = 280
2323

2424
self.initUI()
25+
self.add_tool_tips_dlg()
2526

2627
def initUI(self):
2728
self.setWindowIcon(QIcon('./assets/about.png'))

0 commit comments

Comments
 (0)