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

Source Code for Module phones.com_lgg4015

  1  ### BITPIM 
  2  ### 
  3  ### Copyright (C) 2005 Joe Pham <djpham@bitpim.org> 
  4  ### 
  5  ### This program is free software; you can redistribute it and/or modify 
  6  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
  7  ### 
  8  ### $Id: com_lgg4015.py 4365 2007-08-17 21:11:59Z djpham $ 
  9   
 10  """Communicate with the LG G4015 cell phone 
 11  """ 
 12   
 13  # standard modules 
 14  import base64 
 15  import sha 
 16  import time 
 17   
 18  # BitPim modules 
 19  import bpcalendar 
 20  import common 
 21  import commport 
 22  import com_etsi 
 23  import guihelper 
 24  import helpids 
 25  import memo 
 26  import nameparser 
 27  import p_lgg4015 
 28  import prototypes 
 29  import sms 
30 31 -class Phone(com_etsi.Phone):
32 """ Talk to the LG G4015 Phone""" 33 34 desc='LG-G4015' 35 helpid=helpids.ID_PHONE_LGG4015 36 protocolclass=p_lgg4015 37 serialsname='lgg4015' 38
39 - def __init__(self, logtarget, commport):
40 super(Phone,self).__init__(logtarget, commport) 41 self.mode=self.MODENONE
42
43 - def getfundamentals(self, results):
44 45 """Gets information fundamental to interoperating with the phone and UI. 46 47 Currently this is: 48 49 - 'uniqueserial' a unique serial number representing the phone 50 - 'groups' the phonebook groups 51 - 'wallpaper-index' map index numbers to names 52 - 'ringtone-index' map index numbers to ringtone names 53 54 This method is called before we read the phonebook data or before we 55 write phonebook data. 56 """ 57 # use a hash of ESN and other stuff (being paranoid) 58 self.setmode(self.MODEMODEM) 59 self.log("Retrieving fundamental phone information") 60 self.log("Reading phone serial number") 61 results['uniqueserial']=sha.new(self.get_sim_id()).hexdigest() 62 # now read groups 63 self.log("Reading group information") 64 results['groups']=self._get_groups() 65 # getting rintone-index 66 self.log('Reading Ringtone Index') 67 results['ringtone-index']=self._get_ringtone_index() 68 # getting wallpaper-index 69 self.log('Reading Wallpaper Index') 70 results['wallpaper-index']=self._get_wallpaper_index() 71 # All done 72 self.log("Fundamentals retrieved") 73 return results
74
75 - def _get_groups(self):
76 res={} 77 self.charset_ascii() 78 _req=self.protocolclass.list_group_req() 79 for i in self.protocolclass.GROUP_INDEX_RANGE: 80 _req.start_index=i 81 _req.end_index=i 82 try: 83 _res=self.sendATcommand(_req, self.protocolclass.list_group_resp) 84 if _res and _res[0].group_name: 85 res[i]={ 'name': _res[0].group_name } 86 except: 87 if __debug__: 88 raise 89 return res
90
91 - def _ringtone_mode(self):
92 _req=self.protocolclass.media_selector_set() 93 _req.media_type=self.protocolclass.MEDIA_RINGTONE 94 self.sendATcommand(_req, None)
95
96 - def _get_ringtone_index(self):
97 """ Return the ringtone index""" 98 res={} 99 # Set the media type to be sound (ringtone) 100 self.charset_ascii() 101 self._ringtone_mode() 102 # and read the list 103 _req=self.protocolclass.media_list_req() 104 _req.start_index=self.protocolclass.MIN_RINGTONE_INDEX 105 _req.end_index=self.protocolclass.MAX_RINGTONE_INDEX 106 _res=self.sendATcommand(_req, self.protocolclass.media_list_resp) 107 for i,e in enumerate(_res): 108 res[i]={ 'name': e.file_name, 'origin': 'ringtone' } 109 return res
110
111 - def _wallpaper_mode(self):
112 _req=self.protocolclass.media_selector_set() 113 _req.media_type=self.protocolclass.MEDIA_WALLPAPER 114 self.sendATcommand(_req, None)
115
116 - def _get_wallpaper_index(self):
117 """ Return the wallpaper index""" 118 res={} 119 # Set the media type to be pic (wallpaper) 120 self.charset_ascii() 121 self._wallpaper_mode() 122 # and read the list 123 _req=self.protocolclass.media_list_req() 124 _req.start_index=self.protocolclass.MIN_WALLPAPER_INDEX 125 _req.end_index=self.protocolclass.MAX_WALLPAPER_INDEX 126 _res=self.sendATcommand(_req, self.protocolclass.media_list_resp) 127 for i,e in enumerate(_res): 128 res[i]={ 'name': e.file_name, 'origin': 'wallpaper' } 129 return res
130 131 # Calendar stuff----------------------------------------------------------- 132 cal_repeat_value={ 133 protocolclass.CAL_REP_DAILY: bpcalendar.RepeatEntry.daily, 134 protocolclass.CAL_REP_WEEKLY: bpcalendar.RepeatEntry.weekly, 135 protocolclass.CAL_REP_MONTHLY: bpcalendar.RepeatEntry.monthly, 136 protocolclass.CAL_REP_YEARLY: bpcalendar.RepeatEntry.yearly } 137 cal_repeat_value_r={ 138 bpcalendar.RepeatEntry.daily: protocolclass.CAL_REP_DAILY, 139 bpcalendar.RepeatEntry.weekly: protocolclass.CAL_REP_WEEKLY, 140 bpcalendar.RepeatEntry.monthly: protocolclass.CAL_REP_MONTHLY, 141 bpcalendar.RepeatEntry.yearly: protocolclass.CAL_REP_YEARLY } 142
143 - def _build_bpcalendar_entry(self, phone_entry):
144 entry=bpcalendar.CalendarEntry() 145 entry.start=phone_entry.date+phone_entry.time 146 entry.end=phone_entry.date+phone_entry.time 147 entry.description=phone_entry.description 148 entry.serials.append({ 'sourcetype': 'phone', 149 'id': phone_entry.index }) 150 entry.alarm=self.protocolclass.CAL_ALARM_VALUE.get(phone_entry.alarm, -1) 151 _rpt_type=self.cal_repeat_value.get(phone_entry.repeat, None) 152 if _rpt_type: 153 # this is a recurrent event 154 rpt=bpcalendar.RepeatEntry(_rpt_type) 155 if _rpt_type!=bpcalendar.RepeatEntry.yearly: 156 rpt.interval=1 157 # repeat forever 158 entry.end=bpcalendar.CalendarEntry.no_end_date 159 entry.repeat=rpt 160 return entry
161
162 - def getcalendar(self, result):
163 self.log("Getting calendar entries") 164 self.setmode(self.MODEMODEM) 165 self.charset_ascii() 166 res={} 167 _req=self.protocolclass.calendar_read_req() 168 _req.start_index=self.protocolclass.CAL_MIN_INDEX 169 _req.end_index=self.protocolclass.CAL_MAX_INDEX 170 _res=self.sendATcommand(_req, self.protocolclass.calendar_read_resp) 171 for e in _res: 172 try: 173 _entry=self._build_bpcalendar_entry(e) 174 res[_entry.id]=_entry 175 except: 176 if __debug__: 177 raise 178 result['calendar']=res 179 return result
180
181 - def _build_phone_cal_entry(self, entry_count, bpentry):
182 entry=self.protocolclass.calendar_write_req() 183 entry.index=entry_count 184 entry.date=bpentry.start[:3] 185 if bpentry.allday: 186 entry.time=(0,0) 187 else: 188 entry.time=bpentry.start[3:] 189 entry.description=bpentry.description 190 # setting the alarm 191 _alarm=self.protocolclass.CAL_ALARM_NONE 192 for e in self.protocolclass.CAL_ALARM_LIST: 193 if bpentry.alarm>=e[0]: 194 _alarm=e[1] 195 break 196 entry.alarm=_alarm 197 # setting repeat value 198 if bpentry.repeat: 199 _rpt_type=self.cal_repeat_value_r.get(bpentry.repeat.repeat_type, 200 self.protocolclass.CAL_REP_NONE) 201 else: 202 _rpt_type=self.protocolclass.CAL_REP_NONE 203 entry.repeat=_rpt_type 204 return entry
205
206 - def savecalendar(self, dict, merge):
207 self.log('Saving calendar entries') 208 self.setmode(self.MODEMODEM) 209 self.charset_ascii() 210 _cal_dict=dict['calendar'] 211 _cal_list=[(x.start, k) for k,x in _cal_dict.items()] 212 _cal_list.sort() 213 _cal_list=_cal_list[:self.protocolclass.CAL_TOTAL_ENTRIES] 214 _pre_write=self.protocolclass.calendar_write_check_req() 215 for i,e in enumerate(_cal_list): 216 _entry=self._build_phone_cal_entry(i, _cal_dict[e[1]]) 217 self.progress(i, self.protocolclass.CAL_TOTAL_ENTRIES, 218 'Writing entry %d: %s'%(i, _entry.description)) 219 try: 220 try: 221 self.sendATcommand(_entry, None) 222 _success=True 223 except: 224 _success=False 225 if not _success: 226 try: 227 self.sendATcommand(_pre_write, None) 228 except: 229 pass 230 self.sendATcommand(_entry, None) 231 except: 232 if __debug__: 233 raise 234 _req=self.protocolclass.calendar_del_req() 235 for i in range(len(_cal_list), self.protocolclass.CAL_TOTAL_ENTRIES): 236 self.progress(i, self.protocolclass.CAL_TOTAL_ENTRIES, 237 'Deleting entry %d'%i) 238 _req.index=i 239 try: 240 self.sendATcommand(_req, None) 241 except: 242 break 243 return dict
244
245 - def charset_ascii(self):
246 """ Set the phone charset to some form of ascii""" 247 _req=self.protocolclass.charset_set_req() 248 _req.charset=self.protocolclass.CHARSET_IRA 249 self.sendATcommand(_req, None)
250 - def charset_base64(self):
251 """ Set the phone charset to Base64 (for binary transmission)""" 252 _req=self.protocolclass.charset_set_req() 253 _req.charset=self.protocolclass.CHARSET_BASE64 254 self.sendATcommand(_req, None)
255 256 # Detect Phone--------------------------------------------------------------
257 - def is_mode_modem(self):
258 try: 259 self.comm.sendatcommand("Z") 260 self.comm.sendatcommand('E0V1') 261 return True 262 except: 263 return False
264
265 - def get_detect_data(self, r):
266 # get detection data 267 r['manufacturer']=self.get_manufacturer_id() 268 r['model']=self.get_model_id() 269 r['firmware_version']=self.get_firmware_version() 270 r['esn']=self.get_sim_id()
271 272 @classmethod
273 - def detectphone(_, coms, likely_ports, res, _module, _log):
274 if not len(likely_ports): 275 return None 276 for port in likely_ports: 277 if not res.has_key(port): 278 res[port]={ 'mode_modem': None, 'mode_brew': None, 279 'manufacturer': None, 'model': None, 280 'firmware_version': None, 'esn': None, 281 'firmwareresponse': None } 282 try: 283 if res[port]['mode_modem']==False or \ 284 res[port]['model']: 285 continue 286 p=Phone(_log, commport.CommConnection(_log, port, timeout=1)) 287 if p.is_mode_modem(): 288 res[port]['mode_modem']=True 289 p.get_detect_data(res[port]) 290 else: 291 res[port]['mode_modem']=False 292 except: 293 # this port is not available 294 if __debug__: 295 raise
296 297 # Phonebook stuff-----------------------------------------------------------
298 - def _build_bp_entry(self, entry, groups, in_sim=False):
299 res={ 'names': [ { 'full': entry.name } ] } 300 _numbers=[] 301 if entry.mobile: 302 _numbers.append({ 'number': entry.mobile, 303 'type': 'cell' }) 304 if entry.home: 305 _numbers.append({ 'number': entry.home, 306 'type': 'home' }) 307 if entry.office: 308 _numbers.append({ 'number': entry.office, 309 'type': 'office'}) 310 if _numbers: 311 res['numbers']=_numbers 312 if entry.email: 313 res['emails']=[{ 'email': entry.email }] 314 if entry.memo: 315 res['memos']=[{ 'memo': entry.memo }] 316 _group=groups.get(entry.group, None) 317 if _group and _group.get('name', None): 318 res['categories']=[{ 'category': _group['name'] }] 319 if entry.sim: 320 res['flags']=[{ 'sim': in_sim }] 321 return res
322
323 - def _get_main_phonebook(self, groups):
324 """return a dict of contacts read off the phone storage area""" 325 # switch to the phone storage 326 _req=self.protocolclass.select_storage_req() 327 _req.storage=self.protocolclass.PB_MEMORY_MAIN 328 self.sendATcommand(_req, None) 329 # read the entries 330 _req=self.protocolclass.read_phonebook_req() 331 _req.start_index=self.protocolclass.PB_MAIN_MIN_INDEX 332 _req.end_index=self.protocolclass.PB_MAIN_MAX_INDEX 333 _res=self.sendATcommand(_req, self.protocolclass.read_phonebook_resp) 334 res={} 335 for e in _res: 336 res[e.index]=self._build_bp_entry(e, groups) 337 return res
338
339 - def _get_sim_phonebook(self, groups):
340 """return a dict of contacts read off the phone SIM card""" 341 # switch to the phone storage 342 _req=self.protocolclass.select_storage_req() 343 _req.storage=self.protocolclass.PB_MEMORY_SIM 344 self.sendATcommand(_req, None) 345 # read the entries 346 _req=self.protocolclass.read_phonebook_req() 347 _req.start_index=self.protocolclass.PB_SIM_MIN_INDEX 348 _req.end_index=self.protocolclass.PB_SIM_MAX_INDEX 349 _res=self.sendATcommand(_req, self.protocolclass.read_sim_phonebook_resp) 350 res={} 351 for e in _res: 352 res[1000+e.index]=self._build_bp_entry(e, groups, in_sim=True) 353 return res
354
355 - def getphonebook(self,result):
356 """Reads the phonebook data. The L{getfundamentals} information will 357 already be in result.""" 358 self.log('Getting phonebook') 359 self.setmode(self.MODEMODEM) 360 self.charset_ascii() 361 _groups=result.get('groups', {}) 362 pb_book=self._get_main_phonebook(_groups) 363 pb_book.update(self._get_sim_phonebook(_groups)) 364 result['phonebook']=pb_book 365 return pb_book
366
367 - def _in_sim(self, entry):
368 """ Return True if this entry has the sim flag set, indicating that 369 it should be stored on the SIM card. 370 """ 371 for l in entry.get('flags', []): 372 if l.has_key('sim'): 373 return l['sim'] 374 return False
375
376 - def _lookup_group(self, entry, groups):
377 try: 378 _name=entry['categories'][0]['category'] 379 except: 380 return 0 381 for k,e in groups.items(): 382 if e['name']==_name: 383 return k 384 return 0
385
386 - def _build_main_entry(self, entry, groups):
387 _req=self.protocolclass.write_phonebook_req() 388 _req.group=self._lookup_group(entry, groups) 389 _req.name=nameparser.getfullname(entry['names'][0]) 390 _req.email=entry.get('emails', [{'email': ''}])[0]['email'] 391 _req.memo=entry.get('memos', [{'memo': ''}])[0]['memo'] 392 for n in entry.get('numbers', []): 393 _type=n['type'] 394 _number=n['number'] 395 if _type=='cell': 396 _req.mobile=_number 397 _req.mobile_type=129 398 elif _type=='home': 399 _req.home=_number 400 _req.home_type=129 401 elif _type=='office': 402 _req.office=_number 403 _req.office_type=129 404 return _req
405
406 - def _build_sim_entry(self, entry, groups):
407 _req=self.protocolclass.write_sim_phonebook_req() 408 _req.group=self._lookup_group(entry, groups) 409 _req.name=nameparser.getfullname(entry['names'][0]) 410 _number=entry.get('numbers', [{'number': ''}])[0]['number'] 411 if _number: 412 _req.number=_number 413 _req.number_type=129 414 return _req
415
416 - def _save_main_phonebook(self, entries, groups):
417 """ got the the phonebook dict and write them out to the phone""" 418 # build the full names & SIM keys 419 _pb_list=[(nameparser.getfullname(e['names'][0]), k) \ 420 for k,e in entries.items() if not self._in_sim(e)] 421 # sort alphabetical order 422 _pb_list.sort() 423 # switch to the main phone storage 424 _req=self.protocolclass.select_storage_req() 425 _req.storage=self.protocolclass.PB_MEMORY_MAIN 426 self.sendATcommand(_req, None) 427 _del_entry=self.protocolclass.del_phonebook_req() 428 # send each entry to the phone 429 _index=self.protocolclass.PB_MAIN_MIN_INDEX 430 for l in _pb_list: 431 _del_entry.index=_index 432 _index+=1 433 self.sendATcommand(_del_entry, None) 434 time.sleep(0.2) 435 _req=self._build_main_entry(entries[l[1]], groups) 436 self.progress(_index, self.protocolclass.PB_MAIN_MAX_INDEX, 437 'Writing entry %d: %s'%(_index, _req.name)) 438 try: 439 self.sendATcommand(_req, None) 440 _retry=False 441 except: 442 _retry=True 443 if _retry: 444 try: 445 self.sendATcommand(_req, None) 446 except: 447 self.log('Failed to write entry %d: %s'%(_index, _req.name)) 448 time.sleep(0.2) 449 # clear out the rest of the phonebook 450 for i in range(_index, self.protocolclass.PB_MAIN_MAX_INDEX+1): 451 self.progress(i, self.protocolclass.PB_MAIN_MAX_INDEX, 452 'Deleting entry %d'%i) 453 try: 454 _del_entry.index=i 455 self.sendATcommand(_del_entry, None) 456 continue 457 except: 458 self.log('Trying to delete entry %d'%i) 459 try: 460 self.sendATcommand(_del_entry, None) 461 except: 462 self.log('Failed to delete entry %d'%i)
463
464 - def _save_sim_phonebook(self, entries, groups):
465 """ got the the phonebook dict and write them out to the phone""" 466 # build the full names & SIM keys 467 _pb_list=[(nameparser.getfullname(e['names'][0]), k) \ 468 for k,e in entries.items() if self._in_sim(e)] 469 # sort alphabetical order 470 _pb_list.sort() 471 # switch to the main phone storage 472 _req=self.protocolclass.select_storage_req() 473 _req.storage=self.protocolclass.PB_MEMORY_SIM 474 self.sendATcommand(_req, None) 475 _del_entry=self.protocolclass.del_phonebook_req() 476 # send each entry to the phone 477 _index=self.protocolclass.PB_SIM_MIN_INDEX 478 for l in _pb_list: 479 _del_entry.index=_index 480 _index+=1 481 self.sendATcommand(_del_entry, None) 482 time.sleep(0.2) 483 _req=self._build_sim_entry(entries[l[1]], groups) 484 self.progress(_index, self.protocolclass.PB_SIM_MAX_INDEX, 485 'Writing SIM entry %d: %s'%(_index, _req.name)) 486 try: 487 self.sendATcommand(_req, None) 488 _retry=False 489 except: 490 _retry=True 491 if _retry: 492 try: 493 self.sendATcommand(_req, None) 494 except: 495 self.log('Failed to write SIM entry %d: %s'%(_index, _req.name)) 496 time.sleep(0.2) 497 # clear out the rest of the phonebook 498 for i in range(_index, self.protocolclass.PB_SIM_MAX_INDEX+1): 499 self.progress(i, self.protocolclass.PB_SIM_MAX_INDEX, 500 'Deleting SIM entry %d'%i) 501 try: 502 _del_entry.index=i 503 self.sendATcommand(_del_entry, None) 504 continue 505 except: 506 self.log('Trying to delete entry %d'%i) 507 try: 508 self.sendATcommand(_del_entry, None) 509 except: 510 self.log('Failed to delete entry %d'%i)
511
512 - def savephonebook(self, data):
513 "Saves out the phonebook" 514 self.log('Writing phonebook') 515 self.setmode(self.MODEMODEM) 516 self.charset_ascii() 517 518 pb_book=data.get('phonebook', {}) 519 pb_groups=data.get('groups', {}) 520 self._save_main_phonebook(pb_book, pb_groups) 521 self._save_sim_phonebook(pb_book, pb_groups) 522 return data
523 524 # Ringtone stuff------------------------------------------------------------
525 - def _del_media_files(self, names):
526 self.charset_ascii() 527 _req=self.protocolclass.del_media_req() 528 for n in names: 529 self.log('Deleting media %s'%n) 530 _req.file_name=n 531 try: 532 self.sendATcommand(_req, None) 533 except: 534 self.log('Failed to delete media %s'%n)
535
536 - def _add_media_file(self, file_name, media_name, media_code, data):
537 """ Add one media ringtone 538 """ 539 if not file_name or not media_name or not data: 540 return False 541 self.log('Writing media %s'%file_name) 542 _media_name='' 543 for s in media_name: 544 _media_name+=s+'\x00' 545 _cmd='AT+DDLW=0,"%s","%s",%d,%d,0,0,0,0\r' % \ 546 (file_name, base64.encodestring(_media_name), len(data), 547 media_code) 548 _data64=base64.encodestring(data) 549 self.comm.write(str(_cmd)) 550 if self.comm.read(4)!='\r\n> ': 551 return False 552 for l in _data64.split('\n'): 553 if l: 554 self.comm.write(l+'\n') 555 time.sleep(0.01) 556 self.comm.write(str('\x1A')) 557 return self.comm.read(6)=='\r\nOK\r\n'
558
559 - def _add_ringtones(self, names, name_dict, media):
560 self.charset_base64() 561 for n in names: 562 _media_key=name_dict[n] 563 if not self._add_media_file(n, common.stripext(n), 20, 564 media[_media_key].get('data', '')): 565 self.log('Failed to send ringtone %s'%n) 566 self.charset_ascii()
567
568 - def saveringtones(self, result, merge):
569 self.log('Saving ringtones') 570 self.setmode(self.MODEMODEM) 571 self.charset_ascii() 572 self._ringtone_mode() 573 574 media=result.get('ringtone', {}) 575 media_index=result.get('ringtone-index', {}) 576 media_names=[x['name'] for x in media.values()] 577 index_names=[x['name'] for x in media_index.values()] 578 del_names=[x for x in index_names if x not in media_names] 579 new_names=[x for x in media_names if x not in index_names] 580 # deleting files 581 self._del_media_files(del_names) 582 # and add new files 583 names_to_keys={} 584 for k,e in media.items(): 585 names_to_keys[e['name']]=k 586 self._add_ringtones(new_names, names_to_keys, media) 587 return result
588
589 - def getringtones(self, result):
590 self.log('Reading ringtones index') 591 self.setmode(self.MODEMODEM) 592 self.charset_ascii() 593 self._ringtone_mode() 594 595 media={} 596 media_index=self._get_ringtone_index() 597 for e in media_index.values(): 598 media[e['name']]='dummy data' 599 result['ringtone']=media 600 result['ringtone-index']=media_index 601 return result
602 603 # Wallpaper stuff-----------------------------------------------------------
604 - def getwallpapers(self, result):
605 self.log('Reading wallpaper index') 606 self.setmode(self.MODEMODEM) 607 self.charset_ascii() 608 self._wallpaper_mode() 609 610 media={} 611 media_index=self._get_wallpaper_index() 612 _dummy_data=file(guihelper.getresourcefile('wallpaper.png'),'rb').read() 613 for e in media_index.values(): 614 media[e['name']]=_dummy_data 615 result['wallpapers']=media 616 result['wallpaper-index']=media_index 617 return result
618
619 - def _add_wallpapers(self, names, name_dict, media):
620 self.charset_base64() 621 for n in names: 622 _media_key=name_dict[n] 623 if not self._add_media_file(n, common.stripext(n), 12, 624 media[_media_key].get('data', '')): 625 self.log('Failed to send wallpaper %s'%n) 626 self.charset_ascii()
627
628 - def savewallpapers(self, result, merge):
629 self.log('Saving wallpapers') 630 self.setmode(self.MODEMODEM) 631 self.charset_ascii() 632 self._wallpaper_mode() 633 634 media=result.get('wallpapers', {}) 635 media_index=result.get('wallpaper-index', {}) 636 media_names=[x['name'] for x in media.values()] 637 index_names=[x['name'] for x in media_index.values()] 638 del_names=[x for x in index_names if x not in media_names] 639 new_names=[x for x in media_names if x not in index_names] 640 # deleting files 641 self._del_media_files(del_names) 642 # and add new files 643 names_to_keys={} 644 for k,e in media.items(): 645 names_to_keys[e['name']]=k 646 self._add_wallpapers(new_names, names_to_keys, media) 647 return result
648 649 # Memo stuff----------------------------------------------------------------
650 - def getmemo(self, result):
651 self.log('Reading Memo') 652 self.setmode(self.MODEMODEM) 653 self.charset_ascii() 654 _req=self.protocolclass.memo_read_req() 655 _res=self.sendATcommand(_req, self.protocolclass.memo_read_resp) 656 res={} 657 for e in _res: 658 _memo=memo.MemoEntry() 659 _memo.text=e.text 660 res[_memo.id]=_memo 661 result['memo']=res 662 return res
663
664 - def savememo(self, result, merge):
665 self.log('Writing Memo') 666 self.setmode(self.MODEMODEM) 667 self.charset_ascii() 668 # first, delete all existing memos 669 _req=self.protocolclass.memo_del_req() 670 for i in range(self.protocolclass.MEMO_MIN_INDEX, 671 self.protocolclass.MEMO_MAX_INDEX+1): 672 _req.index=i 673 try: 674 self.sendATcommand(_req, None) 675 except: 676 pass 677 # then update with new ones 678 _memo_dict=result.get('memo', {}) 679 _keys=_memo_dict.keys() 680 _keys.sort() 681 _req=self.protocolclass.memo_write_req() 682 for k in _keys: 683 _req.text=_memo_dict[k].text 684 try: 685 self.sendATcommand(_req, None) 686 except: 687 self.log('Failed to write memo %s'%_req.text) 688 return _memo_dict
689 690 # SMS Stuff-----------------------------------------------------------------
691 - def _process_sms(self, _resp, res):
692 # extract the SMS messages from the respons string & update the dict 693 for i in range(0, len(_resp), 2): 694 try: 695 _entry=self.protocolclass.sms_msg_list_header() 696 _buf=prototypes.buffer(_resp[i]) 697 _entry.readfrombuffer(_buf, logtitle="SMS #"+i) 698 _sms=sms.SMSEntry() 699 if _entry.msg_type==self.protocolclass.SMS_MSG_REC_UNREAD or \ 700 _entry.msg_type==self.protocolclass.SMS_MSG_REC_READ: 701 # unread/read inbox 702 _sms._from=_entry.address 703 _sms.folder=sms.SMSEntry.Folder_Inbox 704 _sms.read=_entry.msg_type==self.protocolclass.SMS_MSG_REC_READ 705 elif _entry.msg_type==self.protocolclass.SMS_MSG_STO_SENT: 706 # outbox 707 _sms.add_recipient(_entry.address) 708 _sms.folder=sms.SMSEntry.Folder_Sent 709 elif _entry.msg_type==self.protocolclass.SMS_MSG_STO_UNSENT: 710 # saved 711 _sms.folder=sms.SMSEntry.Folder_Saved 712 _sms.add_recipient(_entry.address) 713 else: 714 self.log('Unknown message type: %s'%_entry.msg_type) 715 _sms=None 716 if _sms: 717 if _entry.timestamp: 718 _sms.datetime=_entry.timestamp 719 _sms.text=_resp[i+1] 720 res[_sms.id]=_sms 721 except: 722 if __debug__: 723 raise 724 return res
725
726 - def getsms(self, result):
727 self.log('Getting SMS Messages') 728 self.setmode(self.MODEMODEM) 729 self.charset_ascii() 730 res={} 731 # set format to text 732 _req=self.protocolclass.sms_format_req() 733 self.sendATcommand(_req, None) 734 self.log('Getting SMS messages from the phone memory') 735 _sms_mem=self.protocolclass.sms_memory_select_req() 736 _sms_mem.list_memory=self.protocolclass.SMS_MEMORY_PHONE 737 self.sendATcommand(_sms_mem, None) 738 _list_sms=self.protocolclass.sms_msg_list_req() 739 _resp=self.sendATcommand(_list_sms, None) 740 self._process_sms(_resp, res) 741 self.log('Getting SMS message from the SIM card') 742 _sms_mem.list_memory=self.protocolclass.SMS_MEMORY_SIM 743 self.sendATcommand(_sms_mem, None) 744 _resp=self.sendATcommand(_list_sms, None) 745 self._process_sms(_resp, res) 746 try: 747 # this is to clear the next error 748 self.sendATcommand(_sms_mem, None) 749 except commport.ATError: 750 pass 751 result['sms']=res 752 return result
753 754 # Call History stuff--------------------------------------------------------
755 - def _get_history_calls(self, log_str, call_type, min_idx, max_idx):
756 self.log(log_str) 757 _sel_mem=self.protocolclass.select_storage_req() 758 _sel_mem.storage=call_type 759 self.sendATcommand(_sel_mem, None) 760 _list_pb=self.protocolclass.read_phonebook_req() 761 _list_pb.start_index=min_idx 762 _list_pb.end_index=max_idx 763 self.sendATcommand(_list_pb, None)
764
765 - def getcallhistory(self, result):
766 self.log('Getting Call History') 767 self.setmode(self.MODEMODEM) 768 self.charset_ascii() 769 res={} 770 for l in self.protocolclass.PB_CALL_HISTORY_INFO: 771 self._get_history_calls(*l) 772 result['call_history']=res 773 return result
774 775 #------------------------------------------------------------------------------- 776 parent_profile=com_etsi.Profile
777 -class Profile(parent_profile):
778 779 serialsname=Phone.serialsname 780 781 WALLPAPER_WIDTH=128 782 WALLPAPER_HEIGHT=128 783 MAX_WALLPAPER_BASENAME_LENGTH=19 784 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ." 785 WALLPAPER_CONVERT_FORMAT="jpg" 786 MAX_RINGTONE_BASENAME_LENGTH=19 787 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ." 788 RINGTONE_LIMITS= { 789 'MAXSIZE': 20480 790 } 791 # use for auto-detection 792 phone_manufacturer='LGE' 793 phone_model='G4015' 794 795 usbids=( ( 0x10AB, 0x10C5, 1), 796 ) 797 deviceclasses=("serial",) 798 799 imageorigins={} 800 imageorigins.update(common.getkv(parent_profile.stockimageorigins, "images")) 801 802 imagetargets={} 803 imagetargets.update(common.getkv(parent_profile.stockimagetargets, "wallpaper", 804 {'width': 128, 'height': 128, 'format': "JPEG"})) 805
806 - def GetImageOrigins(self):
807 # Note: only return origins that you can write back to the phone 808 return self.imageorigins
809
810 - def GetTargetsForImageOrigin(self, origin):
811 # right now, supporting just 'images' origin 812 if origin=='images': 813 return self.imagetargets
814
815 - def __init__(self):
816 parent_profile.__init__(self)
817 818 _supportedsyncs=( 819 ('phonebook', 'read', None), # all phonebook reading 820 ('phonebook', 'write', 'OVERWRITE'), # only overwriting phonebook 821 ('calendar', 'read', None), # all calendar reading 822 ('calendar', 'write', 'OVERWRITE'), # only overwriting calendar 823 ('ringtone', 'read', None), # all ringtone reading 824 ('ringtone', 'write', 'OVERWRITE'), 825 ('wallpaper', 'read', None), # all wallpaper reading 826 ('wallpaper', 'write', 'OVERWRITE'), 827 ('memo', 'read', None), # all memo list reading DJP 828 ('memo', 'write', 'OVERWRITE'), # all memo list writing DJP 829 ('sms', 'read', None), # all SMS list reading DJP 830 ('call_history', 'read', None), 831 ) 832
833 - def convertphonebooktophone(self, helper, data):
834 return data
835