PyXR

c:\projects\bitpim\src \ phones \ com_lgg4015.py



0001 ### BITPIM
0002 ###
0003 ### Copyright (C) 2005 Joe Pham <djpham@bitpim.org>
0004 ###
0005 ### This program is free software; you can redistribute it and/or modify
0006 ### it under the terms of the BitPim license as detailed in the LICENSE file.
0007 ###
0008 ### $Id: com_lgg4015.py 4365 2007-08-17 21:11:59Z djpham $
0009 
0010 """Communicate with the LG G4015 cell phone
0011 """
0012 
0013 # standard modules
0014 import base64
0015 import sha
0016 import time
0017 
0018 # BitPim modules
0019 import bpcalendar
0020 import common
0021 import commport
0022 import com_etsi
0023 import guihelper
0024 import helpids
0025 import memo
0026 import nameparser
0027 import p_lgg4015
0028 import prototypes
0029 import sms
0030 
0031 class Phone(com_etsi.Phone):
0032     """ Talk to the LG G4015 Phone"""
0033 
0034     desc='LG-G4015'
0035     helpid=helpids.ID_PHONE_LGG4015
0036     protocolclass=p_lgg4015
0037     serialsname='lgg4015'
0038 
0039     def __init__(self, logtarget, commport):
0040         super(Phone,self).__init__(logtarget, commport)
0041         self.mode=self.MODENONE
0042 
0043     def getfundamentals(self, results):
0044 
0045         """Gets information fundamental to interoperating with the phone and UI.
0046 
0047         Currently this is:
0048 
0049           - 'uniqueserial'     a unique serial number representing the phone
0050           - 'groups'           the phonebook groups
0051           - 'wallpaper-index'  map index numbers to names
0052           - 'ringtone-index'   map index numbers to ringtone names
0053 
0054         This method is called before we read the phonebook data or before we
0055         write phonebook data.
0056         """
0057         # use a hash of ESN and other stuff (being paranoid)
0058         self.setmode(self.MODEMODEM)
0059         self.log("Retrieving fundamental phone information")
0060         self.log("Reading phone serial number")
0061         results['uniqueserial']=sha.new(self.get_sim_id()).hexdigest()
0062         # now read groups
0063         self.log("Reading group information")
0064         results['groups']=self._get_groups()
0065         # getting rintone-index
0066         self.log('Reading Ringtone Index')
0067         results['ringtone-index']=self._get_ringtone_index()
0068         # getting wallpaper-index
0069         self.log('Reading Wallpaper Index')
0070         results['wallpaper-index']=self._get_wallpaper_index()
0071         # All done
0072         self.log("Fundamentals retrieved")
0073         return results
0074 
0075     def _get_groups(self):
0076         res={}
0077         self.charset_ascii()
0078         _req=self.protocolclass.list_group_req()
0079         for i in self.protocolclass.GROUP_INDEX_RANGE:
0080             _req.start_index=i
0081             _req.end_index=i
0082             try:
0083                 _res=self.sendATcommand(_req, self.protocolclass.list_group_resp)
0084                 if _res and _res[0].group_name:
0085                     res[i]={ 'name': _res[0].group_name }
0086             except:
0087                 if __debug__:
0088                     raise
0089         return res
0090 
0091     def _ringtone_mode(self):
0092         _req=self.protocolclass.media_selector_set()
0093         _req.media_type=self.protocolclass.MEDIA_RINGTONE
0094         self.sendATcommand(_req, None)
0095 
0096     def _get_ringtone_index(self):
0097         """ Return the ringtone index"""
0098         res={}
0099         # Set the media type to be sound (ringtone)
0100         self.charset_ascii()
0101         self._ringtone_mode()
0102         # and read the list
0103         _req=self.protocolclass.media_list_req()
0104         _req.start_index=self.protocolclass.MIN_RINGTONE_INDEX
0105         _req.end_index=self.protocolclass.MAX_RINGTONE_INDEX
0106         _res=self.sendATcommand(_req, self.protocolclass.media_list_resp)
0107         for i,e in enumerate(_res):
0108             res[i]={ 'name': e.file_name, 'origin': 'ringtone' }
0109         return res
0110 
0111     def _wallpaper_mode(self):
0112         _req=self.protocolclass.media_selector_set()
0113         _req.media_type=self.protocolclass.MEDIA_WALLPAPER
0114         self.sendATcommand(_req, None)
0115 
0116     def _get_wallpaper_index(self):
0117         """ Return the wallpaper index"""
0118         res={}
0119         # Set the media type to be pic (wallpaper)
0120         self.charset_ascii()
0121         self._wallpaper_mode()
0122         # and read the list
0123         _req=self.protocolclass.media_list_req()
0124         _req.start_index=self.protocolclass.MIN_WALLPAPER_INDEX
0125         _req.end_index=self.protocolclass.MAX_WALLPAPER_INDEX
0126         _res=self.sendATcommand(_req, self.protocolclass.media_list_resp)
0127         for i,e in enumerate(_res):
0128             res[i]={ 'name': e.file_name, 'origin': 'wallpaper' }
0129         return res
0130 
0131     # Calendar stuff-----------------------------------------------------------
0132     cal_repeat_value={
0133         protocolclass.CAL_REP_DAILY: bpcalendar.RepeatEntry.daily,
0134         protocolclass.CAL_REP_WEEKLY: bpcalendar.RepeatEntry.weekly,
0135         protocolclass.CAL_REP_MONTHLY: bpcalendar.RepeatEntry.monthly,
0136         protocolclass.CAL_REP_YEARLY: bpcalendar.RepeatEntry.yearly }
0137     cal_repeat_value_r={
0138         bpcalendar.RepeatEntry.daily: protocolclass.CAL_REP_DAILY,
0139         bpcalendar.RepeatEntry.weekly: protocolclass.CAL_REP_WEEKLY,
0140         bpcalendar.RepeatEntry.monthly: protocolclass.CAL_REP_MONTHLY,
0141         bpcalendar.RepeatEntry.yearly: protocolclass.CAL_REP_YEARLY }
0142 
0143     def _build_bpcalendar_entry(self, phone_entry):
0144         entry=bpcalendar.CalendarEntry()
0145         entry.start=phone_entry.date+phone_entry.time
0146         entry.end=phone_entry.date+phone_entry.time
0147         entry.description=phone_entry.description
0148         entry.serials.append({ 'sourcetype': 'phone',
0149                                'id': phone_entry.index })
0150         entry.alarm=self.protocolclass.CAL_ALARM_VALUE.get(phone_entry.alarm, -1)
0151         _rpt_type=self.cal_repeat_value.get(phone_entry.repeat, None)
0152         if _rpt_type:
0153             # this is a recurrent event
0154             rpt=bpcalendar.RepeatEntry(_rpt_type)
0155             if _rpt_type!=bpcalendar.RepeatEntry.yearly:
0156                 rpt.interval=1
0157             # repeat forever
0158             entry.end=bpcalendar.CalendarEntry.no_end_date
0159             entry.repeat=rpt
0160         return entry
0161         
0162     def getcalendar(self, result):
0163         self.log("Getting calendar entries")
0164         self.setmode(self.MODEMODEM)
0165         self.charset_ascii()
0166         res={}
0167         _req=self.protocolclass.calendar_read_req()
0168         _req.start_index=self.protocolclass.CAL_MIN_INDEX
0169         _req.end_index=self.protocolclass.CAL_MAX_INDEX
0170         _res=self.sendATcommand(_req, self.protocolclass.calendar_read_resp)
0171         for e in _res:
0172             try:
0173                 _entry=self._build_bpcalendar_entry(e)
0174                 res[_entry.id]=_entry
0175             except:
0176                 if __debug__:
0177                     raise
0178         result['calendar']=res
0179         return result
0180 
0181     def _build_phone_cal_entry(self, entry_count, bpentry):
0182         entry=self.protocolclass.calendar_write_req()
0183         entry.index=entry_count
0184         entry.date=bpentry.start[:3]
0185         if bpentry.allday:
0186             entry.time=(0,0)
0187         else:
0188             entry.time=bpentry.start[3:]
0189         entry.description=bpentry.description
0190         # setting the alarm
0191         _alarm=self.protocolclass.CAL_ALARM_NONE
0192         for e in self.protocolclass.CAL_ALARM_LIST:
0193             if bpentry.alarm>=e[0]:
0194                 _alarm=e[1]
0195                 break
0196         entry.alarm=_alarm
0197         # setting repeat value
0198         if bpentry.repeat:
0199             _rpt_type=self.cal_repeat_value_r.get(bpentry.repeat.repeat_type,
0200                                                   self.protocolclass.CAL_REP_NONE)
0201         else:
0202             _rpt_type=self.protocolclass.CAL_REP_NONE
0203         entry.repeat=_rpt_type
0204         return entry
0205 
0206     def savecalendar(self, dict, merge):
0207         self.log('Saving calendar entries')
0208         self.setmode(self.MODEMODEM)
0209         self.charset_ascii()
0210         _cal_dict=dict['calendar']
0211         _cal_list=[(x.start, k) for k,x in _cal_dict.items()]
0212         _cal_list.sort()
0213         _cal_list=_cal_list[:self.protocolclass.CAL_TOTAL_ENTRIES]
0214         _pre_write=self.protocolclass.calendar_write_check_req()
0215         for i,e in enumerate(_cal_list):
0216             _entry=self._build_phone_cal_entry(i, _cal_dict[e[1]])
0217             self.progress(i, self.protocolclass.CAL_TOTAL_ENTRIES,
0218                           'Writing entry %d: %s'%(i, _entry.description))
0219             try:
0220                 try:
0221                     self.sendATcommand(_entry, None)
0222                     _success=True
0223                 except:
0224                     _success=False
0225                 if not _success:
0226                     try:
0227                         self.sendATcommand(_pre_write, None)
0228                     except:
0229                         pass
0230                     self.sendATcommand(_entry, None)
0231             except:
0232                 if __debug__:
0233                     raise
0234         _req=self.protocolclass.calendar_del_req()
0235         for i in range(len(_cal_list), self.protocolclass.CAL_TOTAL_ENTRIES):
0236             self.progress(i, self.protocolclass.CAL_TOTAL_ENTRIES,
0237                           'Deleting entry %d'%i)
0238             _req.index=i
0239             try:
0240                 self.sendATcommand(_req, None)
0241             except:
0242                 break
0243         return dict
0244 
0245     def charset_ascii(self):
0246         """ Set the phone charset to some form of ascii"""
0247         _req=self.protocolclass.charset_set_req()
0248         _req.charset=self.protocolclass.CHARSET_IRA
0249         self.sendATcommand(_req, None)
0250     def charset_base64(self):
0251         """ Set the phone charset to Base64 (for binary transmission)"""
0252         _req=self.protocolclass.charset_set_req()
0253         _req.charset=self.protocolclass.CHARSET_BASE64
0254         self.sendATcommand(_req, None)
0255 
0256     # Detect Phone--------------------------------------------------------------
0257     def is_mode_modem(self):
0258         try:
0259             self.comm.sendatcommand("Z")
0260             self.comm.sendatcommand('E0V1')
0261             return True
0262         except:
0263             return False
0264 
0265     def get_detect_data(self, r):
0266         # get detection data
0267         r['manufacturer']=self.get_manufacturer_id()
0268         r['model']=self.get_model_id()
0269         r['firmware_version']=self.get_firmware_version()
0270         r['esn']=self.get_sim_id()
0271 
0272     @classmethod
0273     def detectphone(_, coms, likely_ports, res, _module, _log):
0274         if not len(likely_ports):
0275             return None
0276         for port in likely_ports:
0277             if not res.has_key(port):
0278                 res[port]={ 'mode_modem': None, 'mode_brew': None,
0279                             'manufacturer': None, 'model': None,
0280                             'firmware_version': None, 'esn': None,
0281                             'firmwareresponse': None }
0282             try:
0283                 if res[port]['mode_modem']==False or \
0284                    res[port]['model']:
0285                     continue
0286                 p=Phone(_log, commport.CommConnection(_log, port, timeout=1))
0287                 if p.is_mode_modem():
0288                     res[port]['mode_modem']=True
0289                     p.get_detect_data(res[port])
0290                 else:
0291                     res[port]['mode_modem']=False
0292             except:
0293                 # this port is not available
0294                 if __debug__:
0295                     raise
0296 
0297     # Phonebook stuff-----------------------------------------------------------
0298     def _build_bp_entry(self, entry, groups, in_sim=False):
0299         res={ 'names': [ { 'full': entry.name } ] }
0300         _numbers=[]
0301         if entry.mobile:
0302             _numbers.append({ 'number': entry.mobile,
0303                               'type': 'cell' })
0304         if entry.home:
0305             _numbers.append({ 'number': entry.home,
0306                               'type': 'home' })
0307         if entry.office:
0308             _numbers.append({ 'number': entry.office,
0309                               'type': 'office'})
0310         if _numbers:
0311             res['numbers']=_numbers
0312         if entry.email:
0313             res['emails']=[{ 'email': entry.email }]
0314         if entry.memo:
0315             res['memos']=[{ 'memo': entry.memo }]
0316         _group=groups.get(entry.group, None)
0317         if _group and _group.get('name', None):
0318             res['categories']=[{ 'category': _group['name'] }]
0319         if entry.sim:
0320             res['flags']=[{ 'sim': in_sim }]
0321         return res
0322         
0323     def _get_main_phonebook(self, groups):
0324         """return a dict of contacts read off the phone storage area"""
0325         # switch to the phone storage
0326         _req=self.protocolclass.select_storage_req()
0327         _req.storage=self.protocolclass.PB_MEMORY_MAIN
0328         self.sendATcommand(_req, None)
0329         # read the entries
0330         _req=self.protocolclass.read_phonebook_req()
0331         _req.start_index=self.protocolclass.PB_MAIN_MIN_INDEX
0332         _req.end_index=self.protocolclass.PB_MAIN_MAX_INDEX
0333         _res=self.sendATcommand(_req, self.protocolclass.read_phonebook_resp)
0334         res={}
0335         for e in _res:
0336             res[e.index]=self._build_bp_entry(e, groups)
0337         return res
0338 
0339     def _get_sim_phonebook(self, groups):
0340         """return a dict of contacts read off the phone SIM card"""
0341         # switch to the phone storage
0342         _req=self.protocolclass.select_storage_req()
0343         _req.storage=self.protocolclass.PB_MEMORY_SIM
0344         self.sendATcommand(_req, None)
0345         # read the entries
0346         _req=self.protocolclass.read_phonebook_req()
0347         _req.start_index=self.protocolclass.PB_SIM_MIN_INDEX
0348         _req.end_index=self.protocolclass.PB_SIM_MAX_INDEX
0349         _res=self.sendATcommand(_req, self.protocolclass.read_sim_phonebook_resp)
0350         res={}
0351         for e in _res:
0352             res[1000+e.index]=self._build_bp_entry(e, groups, in_sim=True)
0353         return res
0354 
0355     def getphonebook(self,result):
0356         """Reads the phonebook data.  The L{getfundamentals} information will
0357         already be in result."""
0358         self.log('Getting phonebook')
0359         self.setmode(self.MODEMODEM)
0360         self.charset_ascii()
0361         _groups=result.get('groups', {})
0362         pb_book=self._get_main_phonebook(_groups)
0363         pb_book.update(self._get_sim_phonebook(_groups))
0364         result['phonebook']=pb_book
0365         return pb_book
0366 
0367     def _in_sim(self, entry):
0368         """ Return True if this entry has the sim flag set, indicating that
0369         it should be stored on the SIM card.
0370         """
0371         for l in entry.get('flags', []):
0372             if l.has_key('sim'):
0373                 return l['sim']
0374         return False
0375 
0376     def _lookup_group(self, entry, groups):
0377         try:
0378             _name=entry['categories'][0]['category']
0379         except:
0380             return 0
0381         for k,e in groups.items():
0382             if e['name']==_name:
0383                 return k
0384         return 0
0385 
0386     def _build_main_entry(self, entry, groups):
0387         _req=self.protocolclass.write_phonebook_req()
0388         _req.group=self._lookup_group(entry, groups)
0389         _req.name=nameparser.getfullname(entry['names'][0])
0390         _req.email=entry.get('emails', [{'email': ''}])[0]['email']
0391         _req.memo=entry.get('memos', [{'memo': ''}])[0]['memo']
0392         for n in entry.get('numbers', []):
0393             _type=n['type']
0394             _number=n['number']
0395             if _type=='cell':
0396                 _req.mobile=_number
0397                 _req.mobile_type=129
0398             elif _type=='home':
0399                 _req.home=_number
0400                 _req.home_type=129
0401             elif _type=='office':
0402                 _req.office=_number
0403                 _req.office_type=129
0404         return _req
0405 
0406     def _build_sim_entry(self, entry, groups):
0407         _req=self.protocolclass.write_sim_phonebook_req()
0408         _req.group=self._lookup_group(entry, groups)
0409         _req.name=nameparser.getfullname(entry['names'][0])
0410         _number=entry.get('numbers', [{'number': ''}])[0]['number']
0411         if _number:
0412             _req.number=_number
0413             _req.number_type=129
0414         return _req
0415 
0416     def _save_main_phonebook(self, entries, groups):
0417         """ got the the phonebook dict and write them out to the phone"""
0418         # build the full names & SIM keys
0419         _pb_list=[(nameparser.getfullname(e['names'][0]), k) \
0420                   for k,e in entries.items() if not self._in_sim(e)]
0421         # sort alphabetical order
0422         _pb_list.sort()
0423         # switch to the main phone storage
0424         _req=self.protocolclass.select_storage_req()
0425         _req.storage=self.protocolclass.PB_MEMORY_MAIN
0426         self.sendATcommand(_req, None)
0427         _del_entry=self.protocolclass.del_phonebook_req()
0428         # send each entry to the phone
0429         _index=self.protocolclass.PB_MAIN_MIN_INDEX
0430         for l in _pb_list:
0431             _del_entry.index=_index
0432             _index+=1
0433             self.sendATcommand(_del_entry, None)
0434             time.sleep(0.2)
0435             _req=self._build_main_entry(entries[l[1]], groups)
0436             self.progress(_index, self.protocolclass.PB_MAIN_MAX_INDEX,
0437                           'Writing entry %d: %s'%(_index, _req.name))
0438             try:
0439                 self.sendATcommand(_req, None)
0440                 _retry=False
0441             except:
0442                 _retry=True
0443             if _retry:
0444                 try:
0445                     self.sendATcommand(_req, None)
0446                 except:
0447                     self.log('Failed to write entry %d: %s'%(_index, _req.name))
0448             time.sleep(0.2)
0449         # clear out the rest of the phonebook
0450         for i in range(_index, self.protocolclass.PB_MAIN_MAX_INDEX+1):
0451             self.progress(i, self.protocolclass.PB_MAIN_MAX_INDEX,
0452                           'Deleting entry %d'%i)
0453             try:
0454                 _del_entry.index=i
0455                 self.sendATcommand(_del_entry, None)
0456                 continue
0457             except:
0458                 self.log('Trying to delete entry %d'%i)
0459             try:
0460                 self.sendATcommand(_del_entry, None)
0461             except:
0462                 self.log('Failed to delete entry %d'%i)
0463 
0464     def _save_sim_phonebook(self, entries, groups):
0465         """ got the the phonebook dict and write them out to the phone"""
0466         # build the full names & SIM keys
0467         _pb_list=[(nameparser.getfullname(e['names'][0]), k) \
0468                   for k,e in entries.items() if self._in_sim(e)]
0469         # sort alphabetical order
0470         _pb_list.sort()
0471         # switch to the main phone storage
0472         _req=self.protocolclass.select_storage_req()
0473         _req.storage=self.protocolclass.PB_MEMORY_SIM
0474         self.sendATcommand(_req, None)
0475         _del_entry=self.protocolclass.del_phonebook_req()
0476         # send each entry to the phone
0477         _index=self.protocolclass.PB_SIM_MIN_INDEX
0478         for l in _pb_list:
0479             _del_entry.index=_index
0480             _index+=1
0481             self.sendATcommand(_del_entry, None)
0482             time.sleep(0.2)
0483             _req=self._build_sim_entry(entries[l[1]], groups)
0484             self.progress(_index, self.protocolclass.PB_SIM_MAX_INDEX,
0485                           'Writing SIM entry %d: %s'%(_index, _req.name))
0486             try:
0487                 self.sendATcommand(_req, None)
0488                 _retry=False
0489             except:
0490                 _retry=True
0491             if _retry:
0492                 try:
0493                     self.sendATcommand(_req, None)
0494                 except:
0495                     self.log('Failed to write SIM entry %d: %s'%(_index, _req.name))
0496             time.sleep(0.2)
0497         # clear out the rest of the phonebook
0498         for i in range(_index, self.protocolclass.PB_SIM_MAX_INDEX+1):
0499             self.progress(i, self.protocolclass.PB_SIM_MAX_INDEX,
0500                           'Deleting SIM entry %d'%i)
0501             try:
0502                 _del_entry.index=i
0503                 self.sendATcommand(_del_entry, None)
0504                 continue
0505             except:
0506                 self.log('Trying to delete entry %d'%i)
0507             try:
0508                 self.sendATcommand(_del_entry, None)
0509             except:
0510                 self.log('Failed to delete entry %d'%i)
0511 
0512     def savephonebook(self, data):
0513         "Saves out the phonebook"
0514         self.log('Writing phonebook')
0515         self.setmode(self.MODEMODEM)
0516         self.charset_ascii()
0517         
0518         pb_book=data.get('phonebook', {})
0519         pb_groups=data.get('groups', {})
0520         self._save_main_phonebook(pb_book, pb_groups)
0521         self._save_sim_phonebook(pb_book, pb_groups)
0522         return data
0523 
0524     # Ringtone stuff------------------------------------------------------------
0525     def _del_media_files(self, names):
0526         self.charset_ascii()
0527         _req=self.protocolclass.del_media_req()
0528         for n in names:
0529             self.log('Deleting media %s'%n)
0530             _req.file_name=n
0531             try:
0532                 self.sendATcommand(_req, None)
0533             except:
0534                 self.log('Failed to delete media %s'%n)
0535 
0536     def _add_media_file(self, file_name, media_name, media_code, data):
0537         """ Add one media ringtone
0538         """
0539         if not file_name or not media_name or not data:
0540             return False
0541         self.log('Writing media %s'%file_name)
0542         _media_name=''
0543         for s in media_name:
0544             _media_name+=s+'\x00'
0545         _cmd='AT+DDLW=0,"%s","%s",%d,%d,0,0,0,0\r' % \
0546               (file_name, base64.encodestring(_media_name), len(data),
0547                media_code)
0548         _data64=base64.encodestring(data)
0549         self.comm.write(str(_cmd))
0550         if self.comm.read(4)!='\r\n> ':
0551             return False
0552         for l in _data64.split('\n'):
0553             if l:
0554                 self.comm.write(l+'\n')
0555                 time.sleep(0.01)
0556         self.comm.write(str('\x1A'))
0557         return self.comm.read(6)=='\r\nOK\r\n'
0558 
0559     def _add_ringtones(self, names, name_dict, media):
0560         self.charset_base64()
0561         for n in names:
0562             _media_key=name_dict[n]
0563             if not self._add_media_file(n, common.stripext(n), 20,
0564                                       media[_media_key].get('data', '')):
0565                 self.log('Failed to send ringtone %s'%n)
0566         self.charset_ascii()
0567         
0568     def saveringtones(self, result, merge):
0569         self.log('Saving ringtones')
0570         self.setmode(self.MODEMODEM)
0571         self.charset_ascii()
0572         self._ringtone_mode()
0573 
0574         media=result.get('ringtone', {})
0575         media_index=result.get('ringtone-index', {})
0576         media_names=[x['name'] for x in media.values()]
0577         index_names=[x['name'] for x in media_index.values()]
0578         del_names=[x for x in index_names if x not in media_names]
0579         new_names=[x for x in media_names if x not in index_names]
0580         # deleting files
0581         self._del_media_files(del_names)
0582         # and add new files
0583         names_to_keys={}
0584         for k,e in media.items():
0585             names_to_keys[e['name']]=k
0586         self._add_ringtones(new_names, names_to_keys, media)
0587         return result
0588 
0589     def getringtones(self, result):
0590         self.log('Reading ringtones index')
0591         self.setmode(self.MODEMODEM)
0592         self.charset_ascii()
0593         self._ringtone_mode()
0594 
0595         media={}
0596         media_index=self._get_ringtone_index()
0597         for e in media_index.values():
0598             media[e['name']]='dummy data'
0599         result['ringtone']=media
0600         result['ringtone-index']=media_index
0601         return result
0602 
0603     # Wallpaper stuff-----------------------------------------------------------
0604     def getwallpapers(self, result):
0605         self.log('Reading wallpaper index')
0606         self.setmode(self.MODEMODEM)
0607         self.charset_ascii()
0608         self._wallpaper_mode()
0609 
0610         media={}
0611         media_index=self._get_wallpaper_index()
0612         _dummy_data=file(guihelper.getresourcefile('wallpaper.png'),'rb').read()
0613         for e in media_index.values():
0614             media[e['name']]=_dummy_data
0615         result['wallpapers']=media
0616         result['wallpaper-index']=media_index
0617         return result
0618 
0619     def _add_wallpapers(self, names, name_dict, media):
0620         self.charset_base64()
0621         for n in names:
0622             _media_key=name_dict[n]
0623             if not self._add_media_file(n, common.stripext(n), 12,
0624                                       media[_media_key].get('data', '')):
0625                 self.log('Failed to send wallpaper %s'%n)
0626         self.charset_ascii()
0627         
0628     def savewallpapers(self, result, merge):
0629         self.log('Saving wallpapers')
0630         self.setmode(self.MODEMODEM)
0631         self.charset_ascii()
0632         self._wallpaper_mode()
0633 
0634         media=result.get('wallpapers', {})
0635         media_index=result.get('wallpaper-index', {})
0636         media_names=[x['name'] for x in media.values()]
0637         index_names=[x['name'] for x in media_index.values()]
0638         del_names=[x for x in index_names if x not in media_names]
0639         new_names=[x for x in media_names if x not in index_names]
0640         # deleting files
0641         self._del_media_files(del_names)
0642         # and add new files
0643         names_to_keys={}
0644         for k,e in media.items():
0645             names_to_keys[e['name']]=k
0646         self._add_wallpapers(new_names, names_to_keys, media)
0647         return result
0648 
0649     # Memo stuff----------------------------------------------------------------
0650     def getmemo(self, result):
0651         self.log('Reading Memo')
0652         self.setmode(self.MODEMODEM)
0653         self.charset_ascii()
0654         _req=self.protocolclass.memo_read_req()
0655         _res=self.sendATcommand(_req, self.protocolclass.memo_read_resp)
0656         res={}
0657         for e in _res:
0658             _memo=memo.MemoEntry()
0659             _memo.text=e.text
0660             res[_memo.id]=_memo
0661         result['memo']=res
0662         return res
0663 
0664     def savememo(self, result, merge):
0665         self.log('Writing Memo')
0666         self.setmode(self.MODEMODEM)
0667         self.charset_ascii()
0668         # first, delete all existing memos
0669         _req=self.protocolclass.memo_del_req()
0670         for i in range(self.protocolclass.MEMO_MIN_INDEX,
0671                        self.protocolclass.MEMO_MAX_INDEX+1):
0672             _req.index=i
0673             try:
0674                 self.sendATcommand(_req, None)
0675             except:
0676                 pass
0677         # then update with new ones
0678         _memo_dict=result.get('memo', {})
0679         _keys=_memo_dict.keys()
0680         _keys.sort()
0681         _req=self.protocolclass.memo_write_req()
0682         for k in _keys:
0683             _req.text=_memo_dict[k].text
0684             try:
0685                 self.sendATcommand(_req, None)
0686             except:
0687                 self.log('Failed to write memo %s'%_req.text)
0688         return _memo_dict
0689 
0690     # SMS Stuff-----------------------------------------------------------------
0691     def _process_sms(self, _resp, res):
0692         # extract the SMS messages from the respons string & update the dict
0693         for i in range(0, len(_resp), 2):
0694             try:
0695                 _entry=self.protocolclass.sms_msg_list_header()
0696                 _buf=prototypes.buffer(_resp[i])
0697                 _entry.readfrombuffer(_buf, logtitle="SMS #"+i)
0698                 _sms=sms.SMSEntry()
0699                 if _entry.msg_type==self.protocolclass.SMS_MSG_REC_UNREAD or \
0700                    _entry.msg_type==self.protocolclass.SMS_MSG_REC_READ:
0701                     # unread/read inbox
0702                     _sms._from=_entry.address
0703                     _sms.folder=sms.SMSEntry.Folder_Inbox
0704                     _sms.read=_entry.msg_type==self.protocolclass.SMS_MSG_REC_READ
0705                 elif _entry.msg_type==self.protocolclass.SMS_MSG_STO_SENT:
0706                     # outbox
0707                     _sms.add_recipient(_entry.address)
0708                     _sms.folder=sms.SMSEntry.Folder_Sent
0709                 elif _entry.msg_type==self.protocolclass.SMS_MSG_STO_UNSENT:
0710                     # saved
0711                     _sms.folder=sms.SMSEntry.Folder_Saved
0712                     _sms.add_recipient(_entry.address)
0713                 else:
0714                     self.log('Unknown message type: %s'%_entry.msg_type)
0715                     _sms=None
0716                 if _sms:
0717                     if _entry.timestamp:
0718                         _sms.datetime=_entry.timestamp
0719                     _sms.text=_resp[i+1]
0720                     res[_sms.id]=_sms
0721             except:
0722                 if __debug__:
0723                     raise
0724         return res
0725 
0726     def getsms(self, result):
0727         self.log('Getting SMS Messages')
0728         self.setmode(self.MODEMODEM)
0729         self.charset_ascii()
0730         res={}
0731         # set format to text
0732         _req=self.protocolclass.sms_format_req()
0733         self.sendATcommand(_req, None)
0734         self.log('Getting SMS messages from the phone memory')
0735         _sms_mem=self.protocolclass.sms_memory_select_req()
0736         _sms_mem.list_memory=self.protocolclass.SMS_MEMORY_PHONE
0737         self.sendATcommand(_sms_mem, None)
0738         _list_sms=self.protocolclass.sms_msg_list_req()
0739         _resp=self.sendATcommand(_list_sms, None)
0740         self._process_sms(_resp, res)
0741         self.log('Getting SMS message from the SIM card')
0742         _sms_mem.list_memory=self.protocolclass.SMS_MEMORY_SIM
0743         self.sendATcommand(_sms_mem, None)
0744         _resp=self.sendATcommand(_list_sms, None)
0745         self._process_sms(_resp, res)
0746         try:
0747             # this is to clear the next error
0748             self.sendATcommand(_sms_mem, None)
0749         except commport.ATError:
0750             pass
0751         result['sms']=res
0752         return result
0753 
0754     # Call History stuff--------------------------------------------------------
0755     def _get_history_calls(self, log_str, call_type, min_idx, max_idx):
0756         self.log(log_str)
0757         _sel_mem=self.protocolclass.select_storage_req()
0758         _sel_mem.storage=call_type
0759         self.sendATcommand(_sel_mem, None)
0760         _list_pb=self.protocolclass.read_phonebook_req()
0761         _list_pb.start_index=min_idx
0762         _list_pb.end_index=max_idx
0763         self.sendATcommand(_list_pb, None)
0764         
0765     def getcallhistory(self, result):
0766         self.log('Getting Call History')
0767         self.setmode(self.MODEMODEM)
0768         self.charset_ascii()
0769         res={}
0770         for l in self.protocolclass.PB_CALL_HISTORY_INFO:
0771             self._get_history_calls(*l)
0772         result['call_history']=res
0773         return result
0774 
0775 #-------------------------------------------------------------------------------
0776 parent_profile=com_etsi.Profile
0777 class Profile(parent_profile):
0778 
0779     serialsname=Phone.serialsname
0780 
0781     WALLPAPER_WIDTH=128
0782     WALLPAPER_HEIGHT=128
0783     MAX_WALLPAPER_BASENAME_LENGTH=19
0784     WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ."
0785     WALLPAPER_CONVERT_FORMAT="jpg"
0786     MAX_RINGTONE_BASENAME_LENGTH=19
0787     RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ."
0788     RINGTONE_LIMITS= {
0789         'MAXSIZE': 20480
0790     }
0791     # use for auto-detection
0792     phone_manufacturer='LGE'
0793     phone_model='G4015'
0794 
0795     usbids=( ( 0x10AB, 0x10C5, 1),
0796         )
0797     deviceclasses=("serial",)
0798 
0799     imageorigins={}
0800     imageorigins.update(common.getkv(parent_profile.stockimageorigins, "images"))
0801   
0802     imagetargets={}
0803     imagetargets.update(common.getkv(parent_profile.stockimagetargets, "wallpaper",
0804                                       {'width': 128, 'height': 128, 'format': "JPEG"}))
0805 
0806     def GetImageOrigins(self):
0807         # Note: only return origins that you can write back to the phone
0808         return self.imageorigins
0809 
0810     def GetTargetsForImageOrigin(self, origin):
0811         # right now, supporting just 'images' origin
0812         if origin=='images':
0813             return self.imagetargets
0814 
0815     def __init__(self):
0816         parent_profile.__init__(self)
0817 
0818     _supportedsyncs=(
0819         ('phonebook', 'read', None),  # all phonebook reading
0820         ('phonebook', 'write', 'OVERWRITE'),  # only overwriting phonebook
0821         ('calendar', 'read', None),   # all calendar reading
0822         ('calendar', 'write', 'OVERWRITE'),   # only overwriting calendar
0823         ('ringtone', 'read', None),   # all ringtone reading
0824         ('ringtone', 'write', 'OVERWRITE'),
0825         ('wallpaper', 'read', None),  # all wallpaper reading
0826         ('wallpaper', 'write', 'OVERWRITE'),
0827         ('memo', 'read', None),     # all memo list reading DJP
0828         ('memo', 'write', 'OVERWRITE'),  # all memo list writing DJP
0829         ('sms', 'read', None),     # all SMS list reading DJP
0830         ('call_history', 'read', None),
0831         )
0832 
0833     def convertphonebooktophone(self, helper, data):
0834         return data
0835 

Generated by PyXR 0.9.4