diff --git a/python/rds_parser_table_qt.py b/python/rds_parser_table_qt.py index ec99247..3f44764 100644 --- a/python/rds_parser_table_qt.py +++ b/python/rds_parser_table_qt.py @@ -27,7 +27,7 @@ import pmt,functools,csv,md5,collections,copy,sqlite3,atexit,time,re,sys from datetime import datetime from datetime import timedelta import multirds.chart as chart -from multirds.tmc_classes import language +from multirds.tmc_classes import language#supported: de, en (both partially) from PyQt4 import Qt, QtCore, QtGui import pprint,code @@ -40,7 +40,6 @@ pr = cProfile.Profile() from PyQt4.QtCore import QObject, pyqtSignal from bitstring import BitArray -#language="de"#currently supported: de, en (both partially) #defined in tmc_classes.py class rds_parser_table_qt_Signals(QObject): @@ -64,11 +63,13 @@ class rds_parser_table_qt(gr.sync_block):#START out_sig=None) if nPorts==1: self.message_port_register_in(pmt.intern('in')) - self.set_msg_handler(pmt.intern('in'), functools.partial(self.handle_msg, port=0)) + self.set_msg_handler(pmt.intern('in'), + functools.partial(self.handle_msg, port=0)) else: for i in range(nPorts): self.message_port_register_in(pmt.intern('in%d'%i)) - self.set_msg_handler(pmt.intern('in%d'%i), functools.partial(self.handle_msg, port=i)) + self.set_msg_handler(pmt.intern('in%d'%i), + functools.partial(self.handle_msg, port=i)) self.nPorts=nPorts self.message_port_register_in(pmt.intern('freq')) self.set_msg_handler(pmt.intern('freq'), self.set_freq) @@ -90,10 +91,12 @@ class rds_parser_table_qt(gr.sync_block):#START self.decoder_frequencies={} self.decoders=[] for i in range(nPorts): - self.decoders.append({'synced':False,'freq':None,'PI':"",'pilot_SNR':0,'decim_mode':0}) + self.decoders.append({'synced':False,'freq':None,'PI':"", + 'pilot_SNR':0,'decim_mode':0}) #self.decoder_synced={} #self.colorder=['ID','freq','name','PTY','AF','time','text','quality','buttons'] - self.colorder=['ID','freq','name','buttons','PTY','AF','time','text','quality','pilot_SNR','RT+'] + self.colorder=['ID','freq','name','buttons','PTY','AF', + 'time','text','quality','pilot_SNR','RT+'] self.workdir=workdir self.PI_dict={}#contains PI:numpackets (string:integer) @@ -121,16 +124,19 @@ class rds_parser_table_qt(gr.sync_block):#START #self.dbc.execute('''CREATE TABLE rtp # (time text,PI text,rtp_string text)''') - reader = csv.reader(open(self.workdir+'RDS_ODA-AIDs_names_only.csv'), delimiter=',', quotechar='"') + reader = csv.reader(open(self.workdir+'RDS_ODA-AIDs_names_only.csv'), + delimiter=',', quotechar='"') reader.next()#skip header for row in reader: self.ODA_application_names[int(row[0])]=row[1] #read RT+ class name list: - reader = csv.reader(open(self.workdir+'RTplus_classnames.csv'), delimiter=',', quotechar='"') + reader = csv.reader(open(self.workdir+'RTplus_classnames.csv'), + delimiter=',', quotechar='"') reader.next()#skip header self.rtp_classnames=dict((int(rows[0]),rows[1]) for rows in reader) #read TMC-event list - reader = csv.reader(open(self.workdir+'event-list_with_forecast_sort.csv'), delimiter=',', quotechar='"') + reader = csv.reader(open(self.workdir+'event-list_with_forecast_sort.csv'), + delimiter=',', quotechar='"') reader.next()#skip header self.ecl_dict=dict((int(rows[0]),rows[1:]) for rows in reader) #Code,Text CEN-English,Text (German),Text (German) kein Quantifier,Text (Quantifier = 1),Text (Quantifier >1),N,Q,T,D,U,C,R ,Comment @@ -142,24 +148,31 @@ class rds_parser_table_qt(gr.sync_block):#START #C: update class: #read update classes - reader = csv.reader(open(self.workdir+'tmc_update_class_names.csv'), delimiter=',', quotechar='"') + reader = csv.reader(open(self.workdir+'tmc_update_class_names.csv'), + delimiter=',', quotechar='"') reader.next()#skip header, "code(C),english,german" if language=="de": - self.tmc_update_class_names=dict((int(rows[0]),rows[2]) for rows in reader)#german names + self.tmc_update_class_names=dict((int(rows[0]),rows[2]) + for rows in reader)#german names else: - self.tmc_update_class_names=dict((int(rows[0]),rows[1]) for rows in reader)#english names + self.tmc_update_class_names=dict((int(rows[0]),rows[1]) + for rows in reader)#english names #read supplementary information code list - reader = csv.reader(open(self.workdir+'label6-supplementary-information-codes.csv'), delimiter=',', quotechar='"') + reader = csv.reader(open(self.workdir+'label6-supplementary-information-codes.csv'), + delimiter=',', quotechar='"') reader.next()#skip header, "code,english,german" if language=="de": - self.label6_suppl_info=dict((int(rows[0]),rows[2]) for rows in reader)#german + self.label6_suppl_info=dict((int(rows[0]),rows[2]) + for rows in reader)#german else: - self.label6_suppl_info=dict((int(rows[0]),rows[1]) for rows in reader)#english + self.label6_suppl_info=dict((int(rows[0]),rows[1]) + for rows in reader)#english #read PTY list f=open(self.workdir+'pty-list.csv') reader = csv.reader(f, delimiter=',', quotechar='"') reader.next()#skip header - self.pty_dict=dict((int(rows[0]),unicode(rows[1],errors='ignore')) for rows in reader) + self.pty_dict=dict((int(rows[0]),unicode(rows[1],errors='ignore')) + for rows in reader) f.close() self.minute_count=0 self.minute_count_max=0 @@ -341,7 +354,9 @@ class rds_parser_table_qt(gr.sync_block):#START self.RDS_data[PI]["TP"]=TP self.RDS_data[PI]["PTY"]=self.pty_dict[PTY] - self.signals.DataUpdateEvent.emit({'PI':PI,'PTY':self.pty_dict[PTY],'TP':TP,'wrong_block_ratio':self.RDS_data[PI]["wrong_block_ratio"],'dots':dots}) + self.signals.DataUpdateEvent.emit({'PI':PI,'PTY':self.pty_dict[PTY], + 'wrong_block_ratio':self.RDS_data[PI]["wrong_block_ratio"], + 'TP':TP,'dots':dots}) #self.signals.DataUpdateEvent.emit({'PI':PI,'PTY':self.pty_dict[PTY],'TP':TP}) @@ -514,9 +529,6 @@ class rds_parser_table_qt(gr.sync_block):#START if(not self.RDS_data[PI].has_key("RT_0")):#initialize variables self.RDS_data[PI]["RT_0"]={"RT":"_"*64,"RT_valid":[False]*64,"RT_all_valid":False} self.RDS_data[PI]["RT_1"]={"RT":"_"*64,"RT_valid":[False]*64,"RT_all_valid":False} - #self.RDS_data[PI]["RT"]="_"*64 - #self.RDS_data[PI]["RT_valid"]=[False]*64 - #self.RDS_data[PI]["RT_all_valid"]=False self.RDS_data[PI]["RT_last_ab_flag"]=2 adr= array[3]&0b00001111 @@ -527,7 +539,6 @@ class rds_parser_table_qt(gr.sync_block):#START #segment=self.decode_chars(chr(array[4])+chr(array[5])+chr(array[6])+chr(array[7])) segment=chr(array[4])+chr(array[5])+chr(array[6])+chr(array[7])#EDIT:latedecode - #print("RT:adress: %d, segment:%s"%(adr,segment)) #self.signals.DataUpdateEvent.emit({'col':5,'row':port,'PI':PI,'groupType':groupType,'adress':adr,'segment':segment}) text_list=list(self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"]) #determine text length: @@ -574,12 +585,18 @@ class rds_parser_table_qt(gr.sync_block):#START if len(self.RDS_data[PI]["internals"]["RT_history"])>10:#only store last 10 RTs self.RDS_data[PI]["internals"]["RT_history"].pop(0) if self.writeDB: - t=(str(datetime.now()),PI,self.RDS_data[PI]["PSN"],"RT",self.decode_chars(rt)) + t=( + str(datetime.now()),PI,self.RDS_data[PI]["PSN"], + "RT",self.decode_chars(rt) + ) db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t) self.RDS_data[PI]["internals"]["last_valid_rt"]=rt try:#save rt+ if it exist if self.writeDB: - t=(str(datetime.now()),PI,self.RDS_data[PI]["PSN"],"RT+",self.decode_chars(str(self.RDS_data[PI]["RT+"]))) + t=(str(datetime.now()),PI, + self.RDS_data[PI]["PSN"],"RT+", + self.decode_chars(str(self.RDS_data[PI]["RT+"])) + ) db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t) except KeyError: pass#no rt+ -> dont save @@ -636,10 +653,7 @@ class rds_parser_table_qt(gr.sync_block):#START self.RDS_data[PI]["AID_list"][AID]["scope"]+="R"#regional if (app_data>>0)&0x1==1: self.RDS_data[PI]["AID_list"][AID]["scope"]+="U"#urban - #self.RDS_data[PI]["AID_list"][AID]["I"]=(app_data>>3)&0x1#international (EUROROAD) - #self.RDS_data[PI]["AID_list"][AID]["N"]=(app_data>>2)&0x1#national - #self.RDS_data[PI]["AID_list"][AID]["R"]=(app_data>>1)&0x1#regional - #self.RDS_data[PI]["AID_list"][AID]["U"]=(app_data>>0)&0x1#urban + elif variant==1: self.RDS_data[PI]["AID_list"][AID]["SID"]=(app_data>>6)&0x3f#service identifier #timing parameters (used to switch away from TMC station without missing messages): @@ -670,10 +684,6 @@ class rds_parser_table_qt(gr.sync_block):#START if self.debug: print("station:%s sent empty 4A group"%self.RDS_data[PI]["PSN"]) else: - #hours=((array[5] & 0x1) << 4) | ((array[6] >> 4) & 0x0f) - #minutes=((array[6] &0x0F)<<2)|((array[7] >>6)&0x3) - #offsetdir=(array[7]>>5)&0x1 - #local_time_offset=0.5*((array[7])&0x1F) if(offsetdir==1): local_time_offset*=-1 try: @@ -712,7 +722,8 @@ class rds_parser_table_qt(gr.sync_block):#START self.IH_data[PI][ih_data]["count"]+=1 self.IH_data[PI][ih_data]["last_time"]=str(datetime.now()) #TMC-alert-c (grouptype mostly 8A): - elif self.RDS_data[PI]["AID_list"].has_key(52550) and self.RDS_data[PI]["AID_list"][52550]["groupType"]==groupType:#TMC alert-C + elif (self.RDS_data[PI]["AID_list"].has_key(52550) + and self.RDS_data[PI]["AID_list"][52550]["groupType"]==groupType):#TMC alert-C tmc_x=array[3]&0x1f #lower 5 bit of block2 tmc_y=(array[4]<<8)|(array[5]) #block3 tmc_z=(array[6]<<8)|(array[7])#block4 @@ -744,34 +755,7 @@ class rds_parser_table_qt(gr.sync_block):#START #~ ltn=1#assume germany TODO:add better error handling #~ if self.log: #~ print("no LTN (yet) for PI:%s"%PI) - #~ if tmc_T == 0: - #~ if tmc_F==1:#single group - - #~ tmc_msg=tmc_message(PI,psn,ltn,tmc_x,tmc_y,tmc_z,datetime_received,self) - #~ self.print_tmc_msg(tmc_msg) - #~ elif tmc_F==0 and Y15==1:#1st group of multigroup - #~ ci=int(tmc_x&0x7) - #~ tmc_msg=tmc_message(PI,psn,ltn,tmc_x,tmc_y,tmc_z,datetime_received,self) - #~ #if self.RDS_data[PI]["internals"]["unfinished_TMC"].has_key(ci): - #~ #print("overwriting parital message") - #~ self.RDS_data[PI]["internals"]["unfinished_TMC"][ci]={"msg":tmc_msg,"time":time.time()} - #~ else: - #~ ci=int(tmc_x&0x7) - #~ if self.RDS_data[PI]["internals"]["unfinished_TMC"].has_key(ci): - #~ tmc_msg=self.RDS_data[PI]["internals"]["unfinished_TMC"][ci]["msg"] - #~ tmc_msg.add_group(tmc_y,tmc_z) - #~ age=time.time()-self.RDS_data[PI]["internals"]["unfinished_TMC"][ci]["time"] - #~ t=(time.time(),PI,age,ci,tmc_msg.is_complete) - #~ #print("%f: continuing message PI:%s,age:%f,ci:%i complete:%i"%t) - #~ self.RDS_data[PI]["internals"]["unfinished_TMC"][ci]["time"]=time.time() - #~ if tmc_msg.is_complete: - #~ self.print_tmc_msg(tmc_msg)#print and store message - #~ del self.RDS_data[PI]["internals"]["unfinished_TMC"][tmc_msg.ci]#delete finished message - #~ else: - #~ #if not ci==0: - #~ #print("ci %i not found, discarding"%ci) - #~ pass - + #~ else:#alert plus or provider info if tmc_T == 1:#rest done by tmc_parser adr=tmc_x&0xf @@ -1020,7 +1004,8 @@ class rds_parser_table_qt(gr.sync_block):#START 0b1100:u"ÁÀÉÈÍÌÓÒÚÙŘČŠŽĐĿ", 0b1101:u"ÂÄÊËÎÏÔÖÛÜřčšžđŀ", 0b1110:u"ÃÅÆŒŷÝÕØÞŊŔĆŚŹŦð", - 0b1111:u"ãåæœŵýõøþŋŕćśźŧ "}#0xff should not occur (not in standard) (but occured 2017-03-04-9:18 , probably transmission error) + 0b1111:u"ãåæœŵýõøþŋŕćśźŧ "}#0xff should not occur (not in standard) + #(but occured 2017-03-04-9:18 , probably transmission error) #charlist=list(charstring) return_string=u"" @@ -1042,15 +1027,18 @@ class rds_parser_table_qt(gr.sync_block):#START #return_string+=unichr(ord(char))#TODO: properly decide for UTF8 or EBU charset except KeyError: return_string+=u"?%02X?"%ord(char)#symbol not decoded - print("symbol not decoded: "+"?%02X?"%ord(char)+"in string:"+return_string) + print("symbol not decoded: "+"?%02X?"%ord(char)+ + "in string:"+return_string) pass if not type(return_string)==unicode: code.interact(local=locals()) return return_string def color_text(self, text, start,end,textcolor,segmentcolor): - #formatted_text="%s%s%s"% (textcolor,text[:start],segmentcolor,text[start:end],textcolor,text[end:]) - #formatted_text="%s%s%s"% (textcolor,text[:start],segmentcolor,text[start:end],textcolor,text[end:]) - formatted_text=("%s"*3)% (textcolor,text[:start],segmentcolor,text[start:end],textcolor,text[end:]) + formatted_text=( + "%s"*3 + )% (textcolor,text[:start], + segmentcolor,text[start:end], + textcolor,text[end:]) return formatted_text class rds_parser_table_qt_Widget(QtGui.QWidget): def __init__(self, signals,label,tableobj): @@ -1075,9 +1063,6 @@ class rds_parser_table_qt_Widget(QtGui.QWidget): self.table.setColumnCount(len(self.colorder)) self.table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) #disallow editing - - ##button.clicked.connect(self.getDetails) - layout.addWidget(self.table) self.table.setHorizontalHeaderLabels(self.colorder) #self.table.setMaximumHeight(300)#TODO use dynamic value @@ -1102,7 +1087,8 @@ class rds_parser_table_qt_Widget(QtGui.QWidget): label_layout = Qt.QHBoxLayout() self.freq_label=QtGui.QLabel("decoder frequencies:") self.freq_label.setWordWrap(True) - self.freq_label.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Ignored))#expand in horizontal direction and only wrap if window too small + self.freq_label.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, + QtGui.QSizePolicy.Ignored))#expand in horizontal direction and only wrap if window too small #self.freq_label.setTextFormat(QtCore.Qt.RichText) #self.freq_label.setTextFormat(QtCore.Qt.PlainText) self.count_label=QtGui.QLabel("count:") @@ -1242,7 +1228,8 @@ class rds_parser_table_qt_Widget(QtGui.QWidget): def showIHdata(self): view=Qt.QDialog() l=QtGui.QLabel("In House Data:\n%s"%pp.pformat(self.tableobj.IH_data)) - l.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse |QtCore.Qt.TextSelectableByKeyboard) + l.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | + QtCore.Qt.TextSelectableByKeyboard) l.setWordWrap(True) #self.IH_data layout=Qt.QVBoxLayout() @@ -1255,10 +1242,12 @@ class rds_parser_table_qt_Widget(QtGui.QWidget): PI=str(self.table.cellWidget(row,PIcol).text()) freq=int(self.tableobj.RDS_data[PI]['AF']['main']) #print("setaudio row:%i, chan:%s, PI:%s,freq:%i"%(row,audio_channel,PI,freq)) - send_pmt = pmt.pmt_to_python.pmt_from_dict({"cmd":"set_audio_freq","chan":audio_channel,"freq":freq}) + send_pmt = pmt.pmt_to_python.pmt_from_dict({"cmd":"set_audio_freq", + "chan":audio_channel,"freq":freq}) self.tableobj.message_port_pub(pmt.intern('ctrl'), send_pmt) #catch: - #print("no freq, cant set decoder")#show notification? popup: too intrusive, log: maybe not visible, other possibility? + #print("no freq, cant set decoder") + #show notification? popup: too intrusive, log: maybe not visible, other possibility? #print("freq not in RX BW")#automatically shift freq-tune? def setAudio2(self,row,audio_channel): @@ -1278,13 +1267,15 @@ class rds_parser_table_qt_Widget(QtGui.QWidget): PIcol=self.colorder.index('ID') PI=str(self.table.cellWidget(row,PIcol).text()) view = chart.DialogViewer() - if self.tableobj.PI_dict.has_key(PI) and self.tableobj.PI_dict[PI]>3:#dont print piechart if no packets received (detected via EON) + if self.tableobj.PI_dict.has_key(PI) and self.tableobj.PI_dict[PI]>3: + #dont print piechart if no packets received (detected via EON) table=chart.DataTable() table.addColumn('groupType') table.addColumn('numPackets') blockcounts=copy.deepcopy(self.tableobj.RDS_data[PI]['blockcounts']) del blockcounts['any'] - #lambda function removes last character of PI string (A or B) and sorts based on integer valure of number in front + #lambda function removes last character of PI string (A or B) + #and sorts based on integer valure of number in front for key in sorted(blockcounts,key=lambda elem: int(elem[0:-1])): count=blockcounts[key] table.addRow([key+": "+str(count),count]) @@ -1298,11 +1289,14 @@ class rds_parser_table_qt_Widget(QtGui.QWidget): del rds_data['PSN_valid'] del rds_data["RT_0"]['RT_valid'] del rds_data["RT_1"]['RT_valid'] - rds_data['internals']['RT_history']=["".join(rt) for rt in rds_data['internals']['RT_history']]#combine char lists into strings (more compact) + rds_data['internals']['RT_history']=["".join(rt) for rt + in rds_data['internals']['RT_history']] + #combine char lists into strings (more compact) except KeyError: pass l=QtGui.QLabel("Data:%s"%pp.pformat(rds_data)) - l.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse |QtCore.Qt.TextSelectableByKeyboard) + l.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | + QtCore.Qt.TextSelectableByKeyboard) l.setWordWrap(True) #l=QtGui.QLabel("Data:")