Package phones :: Module com_lgtm520
[hide private]
[frames] | no frames]

Source Code for Module phones.com_lgtm520

  1  ### BITPIM 
  2  ### 
  3  ### Copyright (C) 2003 Roger Binns <rogerb@rogerbinns.com> 
  4  ### Copyright (C) 2003 Scott Craig <scott.craig@shaw.ca> 
  5  ### Copyright (C) 2003 Alan Gonzalez <agonzalez@yahoo.com> 
  6  ### 
  7  ### This program is free software; you can redistribute it and/or modify 
  8  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
  9  ### 
 10  ### $Id: com_lgtm520.py 4543 2008-01-04 23:44:24Z djpham $ 
 11   
 12  "Talk to the LG TM520/VX10 cell phone" 
 13   
 14  # standard modules 
 15  import re 
 16  import time 
 17  import cStringIO 
 18  import sha 
 19   
 20  # my modules 
 21  import common 
 22  import p_lgtm520 
 23  import com_brew 
 24  import com_phone 
 25  import com_lg 
 26  import prototypes 
 27   
 28  typemap = { 
 29              'fwd': ( 'home', 'office', 'cell', 'pager', 'data' ), 
 30              'rev': { 'home': 0, 'office': 1, 'cell': 2, 'pager': 3, 'data': 4, 'fax': 4 } 
 31            } 
 32   
33 -class Phone(com_phone.Phone,com_brew.BrewProtocol,com_lg.LGPhonebook):
34 "Talk to the LG TM520/VX10 cell phone" 35 desc="LG-TM520/VX10" 36 protocolclass=p_lgtm520 37 serialsname='lgtm520' 38 39 ringtonelocations=( 40 # offset, index file, files location, type, maximumentries 41 # There really isn't an index file 42 ( 0, "", "ringer", "ringers", 5), 43 # phonebook linkage 44 #( 0, "pim/midiringer.dat", "ringer", "ringers", 199), 45 # main ringer 46 #( 0, "pim/ringtitle.dat", "ringer", "ringers", 1), 47 ) 48 49 builtinringtones=( 'Standard1', 'Standard2', 'Standard3', 'Standard4', 50 'Standard5', 'Radetzky March', 'Nocturn', 'Carmen', 51 'La Traviata', 'Liberty Bell', 'Semper Fidelis', 52 'Take Me Out', 'Turkey In The Straw', 'We Wish...', 53 'Csikos Post', 'Bumble Bee Twist', 'Badinerie', 54 'Silken Ladder', 'Chestnut' ) 55 56 # phone uses Jan 1, 1980 as epoch. Python uses Jan 1, 1970. This is difference 57 # plus a fudge factor of 5 days, 20 hours for no reason I can find 58 _tm520epochtounix=315532800+460800 59 _brewepochtounix=315532800+460800 # trying to override inherited entry 60 _calrepeatvalues={ 0: None, 1: None, 2: 'daily' } 61 62 getwallpapers=None 63
64 - def __init__(self, logtarget, commport):
65 com_phone.Phone.__init__(self, logtarget, commport) 66 com_brew.BrewProtocol.__init__(self) 67 com_lg.LGPhonebook.__init__(self) 68 self.log("Attempting to contact phone") 69 self.mode=self.MODENONE
70
71 - def getfundamentals(self, results):
72 """Gets information fundamental to interopating with the phone and UI.""" 73 74 # use a hash of ESN and other stuff (being paranoid) 75 self.log("Retrieving fundamental phone information") 76 self.log("Phone serial number") 77 results['uniqueserial']=sha.new(self.getfilecontents("nvm/$SYS.ESN")).hexdigest() 78 results['ringtone-index'] = {} 79 ringcount = 1 80 for r in self.builtinringtones: 81 results['ringtone-index'][ringcount] = {'name': r, 'origin': 'builtin'} 82 ringcount += 1 83 84 try: 85 ringers=self.getfilesystem('ringer') 86 for r in ringers.keys(): 87 results['ringtone-index'][ringcount] = {'name': r[len('ringer/'):], 'origin': 'ringers'} 88 ringcount +=1 89 except com_brew.BrewNoSuchDirectoryException: 90 self.log("Ringer directory doesn't exist, firmware might not be download capable") 91 self.log("Fundamentals retrieved") 92 return results
93
94 - def pbinit(self):
95 self.mode = self.MODEPHONEBOOK 96 self.sendpbcommand(self.protocolclass.pbstartsyncrequest(), self.protocolclass.pbstartsyncresponse) 97 98 self.mode = self.MODEBREW 99 res=self.sendpbcommand(self.protocolclass.pbinforequest(), self.protocolclass.pbinforesponse) 100 101 return res.numentries
102
103 - def pbend(self):
104 req=self.protocolclass.pbendsyncrequest() 105 self.sendpbcommand(req, self.protocolclass.pbendsyncresponse)
106
107 - def pregetpb(self, result):
108 index={} 109 try: 110 buf=prototypes.buffer(self.getfilecontents("pim/midiringer.dat")) 111 except com_brew.BrewNoSuchFileException: 112 # file may not exist 113 result['intermediate'] = index 114 return 115 g=self.protocolclass.ringindex() 116 g.readfrombuffer(buf, logtitle="ringer index") 117 for i in g.items: 118 if i.name != "default": 119 index[i.index+1]=i.name[len('ringer/'):] 120 result['intermediate'] = index
121
122 - def postgetdb(self, result):
123 #cats=[] 124 #for i in result['groups']: 125 # if result['groups'][i]['name']!='No Group': 126 # cats.append(result['groups'][i]['name']) 127 #result['categories'] = cats 128 del result['intermediate']
129
130 - def getphonebook(self,result):
131 """Reads the phonebook data. The L{getfundamentals} information will 132 already be in result.""" 133 pbook={} 134 # Bug in the phone. if you repeatedly read the phone book it starts 135 # returning a random number as the number of entries. We get around 136 # this by switching into brew mode which clears that. 137 #self.mode=self.MODENONE 138 #self.setmode(self.MODEBREW) 139 140 self.pregetpb(result) 141 self.log("Reading number of phonebook entries") 142 143 numentries=self.pbinit() 144 self.log("There are %d entries" % (numentries,)) 145 for i in range(0, numentries): 146 ### Read current entry 147 req=self.protocolclass.pbreadentryrequest() 148 res=self.sendpbcommand(req, self.protocolclass.pbreadentryresponse) 149 self.log("Read entry "+`i`+" - "+res.entry.name) 150 entry=self.extractphonebookentry(res.entry, result) 151 pbook[i]=entry 152 self.progress(i, numentries, res.entry.name) 153 #### Advance to next entry 154 req=self.protocolclass.pbnextentryrequest() 155 self.sendpbcommand(req, self.protocolclass.pbnextentryresponse) 156 157 self.progress(numentries, numentries, "Phone book read completed") 158 result['phonebook']=pbook 159 self.pbend() 160 self.postgetdb(result) 161 162 print "returning keys",result.keys() 163 return pbook
164
165 - def extractphonebookentry(self, entry, fundamentals):
166 """Return a phonebook entry in BitPim format""" 167 res={} 168 # serials 169 res['serials']=[ {'sourcetype': self.serialsname, 'serial1': entry.serial1, 'serial2': entry.serial2, 170 'sourceuniqueid': fundamentals['uniqueserial']} ] 171 # only one name 172 res['names']=[ {'full': entry.name} ] 173 # only one email 174 if len(entry.email) > 0: res['emails']=[ {'email': entry.email} ] 175 res['flags'] = [] 176 # we only supply secret/voicetag if it is true 177 if entry.secret: res['flags'].append({'secret': entry.secret }) 178 if entry.voicetag: res['flags'].append({'voicetag': entry.voicetag }) 179 180 # ringtones 181 res['ringtones'] = [] 182 if entry.ringtone > 0: 183 # individual ringtone 184 if entry.ringtone > len(self.builtinringtones): 185 # custom individual ringtone 186 try: 187 res['ringtones'].append({'ringtone': fundamentals['intermediate'][entry.entrynumber], 'use': 'call'}) 188 except: 189 self.log('Custom ringtone not properly assigned for '+entry.name) 190 else: 191 # stock individual ringtone 192 res['ringtones'].append({'ringtone': fundamentals['ringtone-index'][entry.ringtone]['name'], 'use': 'call'}) 193 # 5 phone numbers 194 res['numbers']=[] 195 numbernumber=0 196 for type in typemap['fwd']: 197 item = entry.numbers[numbernumber] 198 if len(item.number) > 0: 199 res['numbers'].append({'number': item.number, 'type': type, 'sum': item.chksum }) 200 if numbernumber == entry.default: res['numbers'][-1]['speeddial'] = entry.entrynumber 201 numbernumber+=1 202 return res
203
204 - def savegroups(self, data): pass
205
206 - def savephonebook(self, data):
207 self.savegroups(data) 208 # To write the phone book, we scan through all existing entries 209 # and record their record number and serials. 210 # We then delete any entries that aren't in data 211 # We then write out our records, usng overwrite or append 212 # commands as necessary 213 serialupdates=[] 214 existingpbook={} # keep track of the phonebook that is on the phone 215 ringindex = {} 216 217 # Ringtones 218 pbook = data['phonebook'] 219 for i in pbook.keys(): 220 if not 'ringtone' in pbook[i]: continue 221 if not pbook[i]['ringtone'] is None and not pbook[i]['ringtone'] in self.builtinringtones: 222 ringindex[pbook[i]['entrynumber']] = pbook[i]['ringtone']; 223 224 ringidxfile=self.protocolclass.ringindex() 225 for i in range(1, 200): 226 ringerentry = self.protocolclass.ringentry() 227 ringerentry.index = i 228 ringerentry.name = '' 229 if i in ringindex: ringerentry.name = 'ringer/'+ringindex[i] 230 ringidxfile.items.append(ringerentry) 231 buf=prototypes.buffer() 232 ringidxfile.writetobuffer(buf, logtitle="Custom ringer index") 233 234 # ::TODO:: this code looks wrong. Why isn't the if before the loop above? 235 # and if the user deleted all ringers then shouldn't the file be truncated 236 # rather than ignored? 237 if len(ringindex) > 0: 238 self.writefile("pim/midiringer.dat", buf.getvalue()) 239 240 #self.mode=self.MODENONE 241 #self.setmode(self.MODEBREW) # see note in getphonebook() for why this is necessary 242 #self.setmode(self.MODEPHONEBOOK) 243 # similar loop to reading 244 numexistingentries=self.pbinit() 245 progressmax=numexistingentries+len(data['phonebook'].keys()) 246 progresscur=0 247 self.log("There are %d existing entries" % (numexistingentries,)) 248 for i in range(0, numexistingentries): 249 ### Read current entry 250 req=self.protocolclass.pbreadentryrequest() 251 res=self.sendpbcommand(req, self.protocolclass.pbreadentryresponse) 252 253 entry={ 'number': res.entry.entrynumber, 'serial1': res.entry.serial1, 254 'serial2': res.entry.serial2, 'name': res.entry.name} 255 assert entry['serial1']==entry['serial2'] # always the same 256 self.log("Reading entry "+`i`+" - "+entry['name']) 257 existingpbook[i]=entry 258 self.progress(progresscur, progressmax, "existing "+entry['name']) 259 #### Advance to next entry 260 req=self.protocolclass.pbnextentryrequest() 261 self.sendpbcommand(req, self.protocolclass.pbnextentryresponse) 262 progresscur+=1 263 # we have now looped around back to begining 264 265 # Find entries that have been deleted 266 pbook=data['phonebook'] 267 dellist=[] 268 for i in range(0, numexistingentries): 269 ii=existingpbook[i] 270 serial=ii['serial1'] 271 item=self._findserial(serial, pbook) 272 if item is None: 273 dellist.append(i) 274 275 progressmax+=len(dellist) # more work to do 276 277 # Delete those entries 278 for i in dellist: 279 progresscur+=1 280 numexistingentries-=1 # keep count right 281 ii=existingpbook[i] 282 self.log("Deleting entry "+`i`+" - "+ii['name']) 283 req=self.protocolclass.pbdeleteentryrequest() 284 req.serial1=ii['serial1'] 285 req.serial2=ii['serial2'] 286 req.entrynumber=ii['number'] 287 self.sendpbcommand(req, self.protocolclass.pbdeleteentryresponse) 288 self.progress(progresscur, progressmax, "Deleting "+ii['name']) 289 # also remove them from existingpbook 290 del existingpbook[i] 291 292 # counter to keep track of record number (otherwise appends don't work) 293 counter=0 294 # Now rewrite out existing entries 295 keys=existingpbook.keys() 296 existingserials=[] 297 keys.sort() # do in same order as existingpbook 298 for i in keys: 299 progresscur+=1 300 ii=pbook[self._findserial(existingpbook[i]['serial1'], pbook)] 301 self.log("Rewriting entry "+`i`+" - "+ii['name']) 302 self.progress(progresscur, progressmax, "Rewriting "+ii['name']) 303 entry=self.makeentry(counter, ii, data) 304 counter+=1 305 existingserials.append(existingpbook[i]['serial1']) 306 req=self.protocolclass.pbupdateentryrequest() 307 req.entry=entry 308 res=self.sendpbcommand(req, self.protocolclass.pbupdateentryresponse) 309 serialupdates.append( ( ii["bitpimserial"], 310 {'sourcetype': self.serialsname, 'serial1': res.serial1, 'serial2': res.serial1, 311 'sourceuniqueid': data['uniqueserial']}) 312 ) 313 assert ii['serial1']==res.serial1 # serial should stay the same 314 315 # Finally write out new entries 316 keys=pbook.keys() 317 keys.sort() 318 for i in keys: 319 ii=pbook[i] 320 if ii['serial1'] in existingserials: 321 continue # already wrote this one out 322 progresscur+=1 323 entry=self.makeentry(counter, ii, data) 324 counter+=1 325 self.log("Appending entry "+ii['name']) 326 self.progress(progresscur, progressmax, "Writing "+ii['name']) 327 req=self.protocolclass.pbappendentryrequest() 328 req.entry=entry 329 res=self.sendpbcommand(req, self.protocolclass.pbappendentryresponse) 330 serialupdates.append( ( ii["bitpimserial"], 331 {'sourcetype': self.serialsname, 'serial1': res.newserial, 'serial2': res.newserial, 332 'sourceuniqueid': data['uniqueserial']}) 333 ) 334 335 self.pbend() 336 data["serialupdates"]=serialupdates 337 if len(ringindex) == 0: return
338 339
340 - def _findserial(self, serial, dict):
341 """Searches dict to find entry with matching serial. If not found, 342 returns None""" 343 for i in dict: 344 if dict[i]['serial1']==serial: 345 return i 346 return None
347
348 - def getcalendar(self,result):
349 res={} 350 # Now read schedule 351 buf=prototypes.buffer(self.getfilecontents("sch/sch_00.dat")) 352 sc=self.protocolclass.schedulefile() 353 sc.readfrombuffer(buf, logtitle="Calendar") 354 self.logdata("Calendar", buf.getdata(), sc) 355 for event in sc.events: 356 entry={} 357 if event.state == 0 or event.repeat == 0: continue # deleted entry 358 if event.date == 0x11223344: continue # blanked entry 359 date = event.date 360 date += self._tm520epochtounix 361 entry['start'] = self.decodedate(date) 362 entry['end'] = self.decodedate(date) 363 entry['pos']=event.pos 364 entry['description'] = event.description 365 if event.pos == 0: entry['description'] = 'Wake Up' 366 entry['alarm'] = 0 367 if event.alarm & 0xB0 == 0xB0: entry['alarm'] = 1 368 entry['ringtone'] = 0 369 entry['changeserial'] = 0 370 entry['repeat'] = self._calrepeatvalues[event.repeat] 371 372 # Hack - using snoozedelay to store the DST flag 373 entry['snoozedelay'] = time.localtime(date)[8] 374 res[event.pos]=entry 375 376 result['calendar']=res 377 return result
378
379 - def savecalendar(self, dict, merge):
380 # ::TODO:: obey merge param 381 # what will be written to the files 382 eventsf=self.protocolclass.schedulefile() 383 384 # what are we working with 385 cal=dict['calendar'] 386 newcal={} 387 keys=cal.keys() 388 keys.sort() 389 390 # number of entries 391 numactiveitems=len(keys) 392 self.log("There are %d calendar entries" % (numactiveitems,)) 393 counter = 1 394 395 # Write out alarm entry - see below for special handling 396 alarm=self.protocolclass.scheduleevent() 397 alarm.pos = 0 398 alarm.date = 0x11223344 399 alarm.state = 0 400 alarm.alarm = 0x80 401 alarm.repeat = 0 402 alarm.description = " NO ENTRY NO ENTRY " 403 404 eventsf.events.append(dummy) 405 # play with each entry 406 for k in keys: 407 # entry is what we will return to user 408 entry=cal[k] 409 data=self.protocolclass.scheduleevent() 410 if counter >= 50: 411 self.log("More than 49 entries in calendar, only writing out the first 49") 412 break 413 data.pos=counter 414 counter+=1 415 entry['pos']=data.pos 416 # simple copy of these fields 417 for field in 'start','description': 418 setattr(data,field,entry[field]) 419 420 data.state = 2 421 data.alarm = 0 422 data.repeat = 1 423 424 dst = -1 425 if entry['snoozedelay']: dst = entry['snoozedelay'] 426 data.date = self.encodedate(entry['start'],dst)-self._tm520epochtounix 427 428 # Special alarm handling - TM520 is not capable of having an alarmed 429 # entry, so we will only alarm on the earliest entry 430 if entry['alarm'] > 0 and ( alarm.date == 0x11223344 or data.date < alarm.date ): 431 alarm.date = data.date 432 alarm.state = 1 433 alarm.alarm = 0xB0 434 alarm.repeat = 1 435 if entry['repeat'] > 0: alarm.repeat = 2 436 437 # put entry in nice shiny new dict we are building 438 newcal[data.pos]=entry 439 eventsf.events.append(data) 440 441 if counter < 50: 442 for i in range(counter, 50): 443 dummy=self.protocolclass.scheduleevent() 444 dummy.pos = i 445 dummy.date = 0x11223344 446 dummy.state = 0 447 dummy.alarm = 0x80 448 dummy.repeat = 0 449 dummy.description = " NO ENTRY NO ENTRY " 450 eventsf.events.append(dummy) 451 452 # scribble everything out 453 buf=prototypes.buffer() 454 eventsf.writetobuffer(buf, logtitle="Writing calendar") 455 self.writefile("sch/sch_00.dat", buf.getvalue()) 456 457 # fix passed in dict 458 dict['calendar']=newcal 459 460 return dict
461
462 - def getringtones(self, result):
463 media = {} 464 try: 465 ringers=self.getfilesystem('ringer') 466 for r in ringers: 467 name = r[len('ringer/'):] 468 media[name] = self.getfilecontents(r) 469 except com_brew.BrewNoSuchDirectoryException: pass 470 result['ringtone'] = media 471 return result
472
473 - def saveringtones(self, results, merge):
474 try: 475 ringers=self.getfilesystem('ringer') 476 for r in ringers.keys(): 477 ringers[r[len('ringer/'):]] = ringers[r] 478 del ringers[r] 479 except com_brew.BrewNoSuchDirectoryException: 480 self.log("Ringer directory doesn't exist, firmware might not be download capable") 481 return results 482 483 index={} 484 for r in results['ringtone-index']: 485 if r['origin'] == 'ringers': index.append(r['name']) 486 487 for r in ringers.keys(): 488 # it is in the original index, are we writing it back out? 489 if r in index and ringers[r]['size'] == len(results['ringtone'][r]): continue 490 else: 491 if not merge or r in index: 492 # go ahead and delete unwanted files 493 print "deleting",r 494 self.rmfile("ringer/"+r) 495 if r in index: self.writefile("ringer/"+r, results['ringtone'][r])
496
497 - def decodedate(self,val):
498 """Unpack 32 bit value into date/time 499 500 @rtype: tuple 501 @return: (year, month, day, hour, minute) 502 """ 503 return time.localtime(val)[:5]
504
505 - def encodedate(self,val,dst):
506 tmp = [] 507 for i in val: tmp.append(i) 508 tmp += [0, 0, 0, dst] 509 return time.mktime(tmp)
510
511 - def _findringtoneindex(self, index, name, pbentryname):
512 if name is None: return 0 513 for i in index: 514 if index[i]['name'] == name: 515 return i 516 self.log("%s: Unable to find ringtone %s in the index. Setting to default." % (pbentryname, name)) 517 return 0
518
519 - def _calcnumsum(self, entry, number):
520 sumtbl = { '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 521 'H': 24, 'T': 36, '#': -13, '*': -6 } 522 entry.number = number 523 entry.chksum = 0 524 lastseven = number 525 if len(lastseven) > 7: lastseven = lastseven[len(lastseven)-7:] 526 if len(lastseven) > 0: 527 for i in lastseven: 528 entry.chksum += sumtbl[i] 529 else: entry.chksum = 255
530
531 - def makeentry(self, counter, entry, dict):
532 e=self.protocolclass.pbentry() 533 e.entrynumber=counter 534 535 for k in entry: 536 # special treatment for lists 537 if k == 'numbers': 538 l=getattr(e,k) 539 for item in entry[k]: 540 num=self.protocolclass.numentry() 541 self._calcnumsum(num, item) 542 l.append(num) 543 elif k == 'ringtone': 544 e.ringtone = self._findringtoneindex(dict['ringtone-index'], entry[k], entry['name']) 545 else: 546 # everything else we just set 547 setattr(e,k,entry[k]) 548 549 return e
550
551 -def phonize(str):
552 """Convert the phone number into something the phone understands 553 554 All digits, P, H, T, * and # are kept, everything else is removed""" 555 return re.sub("[^0-9HPT#*]", "", str)
556 557
558 -class Profile(com_phone.Profile):
559 serialsname='lgtm520' 560 WALLPAPER_WIDTH=100 561 WALLPAPER_HEIGHT=100 562 MAX_WALLPAPER_BASENAME_LENGTH=19 563 MAX_RINGTONE_BASENAME_LENGTH=19 564 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ." 565 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ." 566 WALLPAPER_CONVERT_FORMAT="bmp" 567 568 usbids = ( ) 569 deviceclasses = ("serial", ) 570 _supportedsyncs=( 571 ('phonebook', 'read', None), # all phonebook reading 572 ('calendar', 'read', None), # all calendar reading 573 ('ringtone', 'read', None), # all ringtone reading 574 ('phonebook', 'write', 'OVERWRITE'), # only overwriting phonebook 575 ('calendar', 'write', 'OVERWRITE'), # only overwriting calendar 576 ('ringtone', 'write', 'MERGE'), 577 ('ringtone', 'write', 'OVERWRITE'), 578 ) 579
580 - def convertphonebooktophone(self, helper, data):
581 "Converts the data to what will be used by the phone" 582 583 results = {} 584 speeddial = {} 585 entrynumber = 1 586 587 for pbentry in data['phonebook']: 588 e = {} # entry out 589 entry = data['phonebook'][pbentry] # entry in 590 591 try: 592 try: 593 e['name'] = helper.getfullname(entry.get('names', []),1,1,16)[0] 594 except IndexError: raise helper.ConversionFailed("No name assigned to entry") 595 try: 596 e['email']= helper.getemails(entry.get('emails', []),0,1,48)[0] 597 except IndexError: e['email'] = "" 598 e['ringtone'] = helper.getringtone(entry.get('ringtones', []), 'call', None) 599 e['secret'] = helper.getflag(entry.get('flags',[]), 'secret', False) 600 e['voicetag'] = helper.getflag(entry.get('flags',[]), 'voicetag', False) 601 e['default'] = 0 602 603 numbers = entry.get('numbers', []) 604 if len(numbers) < 1: raise helper.ConversionFailed("Too few numbers. Need at least 1 number") 605 e['numbers']=[ '', '', '', '', '' ] 606 available = 5 607 deferred = [] 608 for num in numbers: 609 number=phonize(num['number']) 610 if len(number) == 0: continue # no actual digits in number 611 if len(number) > 32: number = number[:32] # truncate long number 612 if available == 0: break # all slots filled 613 if not 'type' in num: 614 deferred.append(num) 615 continue 616 elif not num['type'] in typemap['rev']: 617 deferred.append(num) 618 continue 619 else: 620 typeidx = typemap['rev'][num['type']] 621 if len(e['numbers'][typeidx]) == 0: 622 e['numbers'][typeidx] = number 623 if 'speeddial' in num and not 'entrynumber' in e: 624 if not num['speeddial'] in speeddial: 625 e['entrynumber'] = num['speeddial'] 626 e['default'] = typeidx 627 available -= 1 628 if available > 0 and len(deferred) > 0: 629 for num in deferred: 630 if available == 0: break 631 number=phonize(num['number']) 632 if len(number) > 32: number = number[:32] # truncate long number 633 for slot in range(0, 5): 634 if len(e['numbers'][slot]) > 0: continue 635 e['numbers'][slot] = number 636 if 'speeddial' in num and not 'entrynumber' in e: 637 if not num['speeddial'] in speeddial: 638 e['entrynumber'] = num['speeddial'] 639 e['default'] = slot 640 available -= 1 641 if available == 5: 642 raise helper.ConversionFailed("The phone numbers didn't have any digits for this entry") 643 if not 'entrynumber' in e: 644 while entrynumber in speedial: 645 entrynumber += 1 646 if entrynumber > 199: 647 self.log("Too many entries in phonebook, only 199 entries supported") 648 break 649 e['entrynumber'] = entrynumber 650 speeddial[e['entrynumber']] = pbentry 651 652 serial1 = helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', 0) 653 serial2 = helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial2', serial1) 654 655 e['serial1'] = serial1 656 e['serial2'] = serial2 657 for ss in entry["serials"]: 658 if ss["sourcetype"]=="bitpim": 659 e['bitpimserial']=ss 660 assert e['bitpimserial'] 661 662 results[pbentry] = e 663 664 except helper.ConversionFailed: continue 665 666 data['phonebook'] = results 667 return data
668