Package phones ::
Module com_samsungscha310
|
|
1
2
3
4
5
6
7
8
9
10 """Communicate with a Samsung SCH-A310"""
11
12
13 import sha
14
15
16 import common
17 import commport
18 import com_brew
19 import com_phone
20 import com_samsung
21
22
23 -class Phone(com_samsung.Phone):
24
25 "Talk to the Samsung SCH-A310 Cell Phone"
26
27 desc="SCH-A310"
28 serialsname='scha310'
29
30 __groups_range=xrange(5)
31 __phone_entries_range=xrange(1,501)
32 __pb_max_entries=23
33 __pb_max_speeddials=500
34 __pb_entry=0
35 __pb_mem_loc=1
36 __pb_group=2
37 __pb_ringtone=3
38 __pb_name=4
39 __pb_speed_dial=5
40 __pb_secret=6
41 __pb_home_num=7
42 __pb_office_num=9
43 __pb_mobile_num=11
44 __pb_pager_num=13
45 __pb_fax_num=15
46 __pb_no_label_num=17
47 __pb_blanks=(19, 20)
48 __pb_email=21
49 __pb_date_time_stamp=22
50 __pb_numbers= ({'home': __pb_home_num},
51 {'office': __pb_office_num},
52 {'cell': __pb_mobile_num},
53 {'pager': __pb_pager_num},
54 {'fax': __pb_fax_num},
55 {'none': __pb_no_label_num})
56 __pb_max_name_len=12
57 __pb_max_number_len=32
58 __pb_max_emails=1
59 builtinringtones=( 'Inactive',
60 'Bell 1', 'Bell 2', 'Bell 3', 'Bell 4', 'Bell 5',
61 'Melody 1', 'Melody 2', 'Melody 3', 'Melody 4', 'Melody 5',
62 'Melody 6', 'Melody 7', 'Melody 8', 'Melody 9', 'Melody 10',
63 'Melody 11', 'Melody 12', 'Melody 13', 'Melody 14', 'Melody 15',
64 'Melody 16')
65
66 __cal_end_datetime_value=None
67
68 - def __init__(self, logtarget, commport):
72
74 """Gets information fundamental to interopating with the phone and UI.
75 Currently this is:
76
77 - 'uniqueserial' a unique serial number representing the phone
78 - 'groups' the phonebook groups
79 - 'wallpaper-index' map index numbers to names
80 - 'ringtone-index' map index numbers to ringtone names
81
82 This method is called before we read the phonebook data or before we
83 write phonebook data.
84 """
85
86 if not self.is_online():
87 self.log("Failed to talk to phone")
88 return results
89
90 self.setmode(self.MODEPHONEBOOK)
91
92
93 self.log("Retrieving fundamental phone information")
94 self.log("Reading phone serial number")
95 results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
96
97
98 self.log("Reading group information")
99 g=self.get_groups(self.__groups_range)
100 groups={}
101
102 for i in range(len(g)):
103 if len(g[i]):
104 groups[i]={ 'name': g[i] }
105 results['groups']=groups
106
107
108 self.log('Reading ringtone index')
109 results['ringtone-index']=self.get_ringtone_index()
110 self.setmode(self.MODEMODEM)
111 self.log("Fundamentals retrieved")
112 return results
113
115 try:
116 s=self.comm.sendatcommand('#PUGSN?')
117 if len(s)==0:
118 return {}
119 except commport.ATError:
120 return {}
121
122 r={}
123 for k in s[1:]:
124 s3=k.split(',')
125 r[int(s3[0])]={ 'name': s3[2], 'origin': 'builtin' }
126 return r
127
147
149 """Reads the phonebook data. The L{getfundamentals} information will
150 already be in result."""
151 if not self.is_online():
152 self.log("Failed to talk to phone")
153 return {}
154 pb_book=self._get_phonebook(result)
155 result['phonebook']=pb_book
156 return pb_book
157
159
160 res={}
161
162
163 res['serials']=[ {'sourcetype': self.serialsname,
164 'sourceuniqueid': fundamentals['uniqueserial'],
165 'serial1': entry[self.__pb_entry],
166 'serial2': entry[self.__pb_mem_loc] }]
167
168
169 res['names']=[ {'full': entry[self.__pb_name].strip('"') } ]
170
171
172 g=fundamentals['groups']
173 i=int(entry[self.__pb_group])
174 res['categories']=[ {'category': g[i]['name'] } ]
175
176
177 s=entry[self.__pb_email].strip('"')
178 if len(s):
179 res['emails']=[ { 'email': s } ]
180
181
182
183 res['flags']=[ { 'secret': entry[self.__pb_secret]=='1' } ]
184
185
186
187
188 r=fundamentals['ringtone-index']
189 try:
190 ringtone_name=r[int(entry[self.__pb_ringtone])]['name']
191 except:
192 ringtone_name=entry[self.__pb_ringtone]
193 res['ringtones']=[ { 'ringtone': ringtone_name,
194 'use': 'call' } ]
195
196
197 speed_dial=int(entry[self.__pb_speed_dial])
198 res['numbers']=[]
199 for k in range(len(self.__pb_numbers)):
200 n=self.__pb_numbers[k]
201 for key in n:
202 if len(entry[n[key]]):
203 if speed_dial==k:
204 res['numbers'].append({ 'number': entry[n[key]],
205 'type': key,
206 'speeddial': int(entry[self.__pb_mem_loc])})
207 else:
208 res['numbers'].append({ 'number': entry[n[key]],
209 'type': key })
210 return res
211
213 "Saves out the phonebook"
214 if not self.is_online():
215 self.log("Failed to talk to phone")
216 return data
217
218 pb_book=data['phonebook']
219 pb_groups=data['groups']
220 self.log('Validating phonebook entries.')
221 del_entries=[]
222 for k in pb_book:
223 if not self.__validate_entry(pb_book[k], pb_groups):
224 self.log('Invalid entry, entry will be not be sent.')
225 del_entries.append(k)
226 for k in del_entries:
227 self.log('Deleting entry '+pb_book[k]['names'][0]['full'])
228 del pb_book[k]
229 self._has_duplicate_speeddial(pb_book)
230 self.log('All entries validated')
231
232 pb_locs=[False]*(len(self.__phone_entries_range)+1)
233 pb_mem=[False]*len(pb_locs)
234
235
236 self.log("Getting current phonebook from the phone")
237 current_pb=self._get_phonebook(data, True)
238
239
240 self.log("Processing speeddial data")
241 for k in pb_book:
242 self._update_speeddial(pb_book[k])
243
244
245 self.setmode(self.MODEPHONEBOOK)
246 self.log("Processing deleted entries")
247 for k1 in current_pb:
248 s1=current_pb[k1]['serials'][0]['serial1']
249 found=False
250 for k2 in pb_book:
251 if self._same_serial1(s1, pb_book[k2]):
252 found=True
253 break
254 if found:
255 pb_locs[int(current_pb[k1]['serials'][0]['serial1'])]=True
256 pb_mem[int(current_pb[k1]['serials'][0]['serial2'])]=True
257 else:
258 self.log("Deleted item: "+current_pb[k1]['names'][0]['full'])
259
260 self.progress(0, 10, "Deleting "+current_pb[k1]['names'][0]['full'])
261 self._del_phone_entry(current_pb[k1])
262 mem_idx, loc_idx = self.__pb_max_speeddials, 1
263
264
265 self.log("Processing new & updated entries")
266 serials_update=[]
267 progresscur, progressmax=1,len(pb_book)
268 ringtone_index=data['ringtone-index']
269 for k in pb_book:
270 if progresscur>len(self.__phone_entries_range):
271 self.log('Max phone entries exceeded: '+str(progresscur))
272 break
273 e=pb_book[k]
274 if not self._has_serial1(e):
275 while pb_locs[loc_idx]:
276 loc_idx += 1
277 pb_locs[loc_idx]=True
278 sd=self._get_speeddial(e)
279 if sd:
280 mem_index=sd
281 pb_mem[sd]=True
282 else:
283 while pb_mem[mem_idx]:
284 mem_idx -= 1
285 pb_mem[mem_idx]=True
286 mem_index=mem_idx
287 self._set_speeddial(e, mem_idx)
288 s1={ 'sourcetype': self.serialsname,
289 'sourceuniqueid': data['uniqueserial'],
290 'serial1': `loc_idx`,
291 'serial2': `mem_index` }
292
293 e['serials'].append(s1)
294 self.log("New entries: Name: "+e['names'][0]['full']+", s1: "+`loc_idx`+", s2: "+`mem_index`)
295 serials_update.append((self._bitpim_serials(e), s1))
296 self.progress(progresscur, progressmax, "Updating "+e['names'][0]['full'])
297 if not self._write_phone_entry(e, pb_groups, ringtone_index):
298 self.log("Failed to save entry: "+e['names'][0]['full'])
299 progresscur += 1
300
301
302 data["serialupdates"]=serials_update
303 self.log("Done")
304 self.setmode(self.MODEMODEM)
305
306 return data
307
308
309
310 - def __validate_entry(self, pb_entry, pb_groups):
311 try:
312
313 name=pb_entry['names'][0]['full'].replace('"', '')
314 if len(name)>self.__pb_max_name_len:
315 name=name[:self.__pb_max_name_len]
316 if pb_entry['names'][0]['full']!=name:
317 pb_entry['names'][0]['full']=name
318
319 has_number_or_email=False
320 if pb_entry.has_key('numbers'):
321 for n in pb_entry['numbers']:
322 num=self.phonize(n['number'])
323 if len(num)>self.__pb_max_number_len:
324 num=num[:self.__pb_max_number_len]
325 if num != n['number']:
326 self.log('Updating number from '+n['number']+' to '+num)
327 n['number']=num
328 try:
329 self._get_number_type(n['type'])
330 except:
331 self.log(n['number']+': setting type to home.')
332 n['type']='home'
333 has_number_or_email=True
334
335 if pb_entry.has_key('emails'):
336 if len(pb_entry['emails'])>self.__pb_max_emails:
337 self.log(name+': Each entry can only have %s emails. The rest will be ignored.'%str(self.__pb_max_emails))
338 email=pb_entry['emails'][0]['email']
339 email.replace('"', '')
340 if len(email)>self.__pb_max_number_len:
341 email=email[:self.__pb_max_number_len]
342 if email!=pb_entry['emails'][0]['email']:
343 pb_entry['emails'][0]['email']=email
344 has_number_or_email=True
345 if not has_number_or_email:
346 self.log(name+': Entry has no numbers or emails')
347
348 return False
349
350 found=False
351 if pb_entry.has_key('categories') and len(pb_entry['categories']):
352 pb_cat=pb_entry['categories'][0]['category']
353 for k in pb_groups:
354 if pb_groups[k]['name']==pb_cat:
355 found=True
356 break
357 if not found:
358 self.log(name+': category set to '+pb_groups[0]['name'])
359 pb_entry['categories']=[{'category': pb_groups[0]['name']}]
360
361 found=False
362 if pb_entry.has_key('ringtones') and len(pb_entry['ringtones']):
363 pb_rt=pb_entry['ringtones'][0]['ringtone']
364
365 for k in self.builtinringtones:
366 if k==pb_rt:
367 found=True
368 break
369 if not found:
370 self.log(name+': ringtone set to '+self.builtinringtones[0])
371 pb_entry['ringtones']=[{'ringtone': self.builtinringtones[0],
372 'use': 'call' }]
373
374 return True
375 except:
376 raise
377
379 b=[False]*(self.__pb_max_speeddials+1)
380 for k in pb_book:
381 try:
382 for k1, kk in enumerate(pb_book[k]['numbers']):
383 sd=kk['speeddial']
384 if sd and b[sd]:
385
386 del pb_book[k]['numbers'][k1]['speeddial']
387 self.log('speeddial %d exists, deleted'%sd)
388 else:
389 b[sd]=True
390 except:
391 pass
392 return False
393
407
409 n=pb_entry.get('numbers', [])
410 for k in n:
411 try:
412 if k['speeddial']:
413 return k['speeddial']
414 except:
415 pass
416 return 0
417
419 if not pb_entry.has_key('numbers'):
420
421 return
422 for k in pb_entry['numbers']:
423 if k.has_key('speeddial'):
424 k['speeddial']=sd
425 return
426 pb_entry['numbers'][0]['speeddial']=sd
427
428 - def _del_phone_entry(self, pb_entry):
429 try:
430 return self.save_phone_entry(self._my_serials(pb_entry)['serial1'])
431 except:
432 return False
433
435 for k in pb_entry['serials']:
436 if k['sourcetype']==self.serialsname and k.has_key('serial1'):
437 return k['serial1']==s1
438 return False
439
441 for k in pb_entry['serials']:
442 if k['sourcetype']==self.serialsname and k.has_key('serial1'):
443 return True
444 return False
445
447 for k in pb_entry['serials']:
448 if k['sourcetype']=="bitpim":
449 return k
450 return {}
451
453 for k in range(len(pb_entry['serials'])):
454 if pb_entry['serials'][k]['sourcetype']==self.serialsname:
455 del pb_entry['serials'][k]
456 return
457
459 for k in pb_entry['serials']:
460 if k['sourcetype']==self.serialsname:
461 return k
462 return {}
463
470
471 - def _write_phone_entry(self, pb_entry, groups, ringtone_index):
472
473 e=['0']*self.__pb_max_entries
474
475 serials=self._my_serials(pb_entry)
476 e[self.__pb_entry]=serials['serial1']
477 e[self.__pb_mem_loc]=serials['serial2']
478
479 grp=0
480 try:
481 grp_name=pb_entry['categories'][0]['category']
482 for k in range(len(groups)):
483 if groups[k]['name']==grp_name:
484 grp=k
485 break
486 except:
487
488 grp, pb_entry['categories']=0, [{'category': groups[0]['name']}]
489 e[self.__pb_group]=`grp`
490
491
492 e[self.__pb_ringtone]=None
493 try:
494 rt=pb_entry['ringtones'][0]['ringtone']
495 for k, n in enumerate(self.builtinringtones):
496 if n==rt:
497 e[self.__pb_ringtone]=`k`
498 break
499 except:
500 pass
501 if e[self.__pb_ringtone] is None:
502 e[self.__pb_ringtone]='0'
503 pb_entry['ringtones']=[ { 'ringtone': self.builtinringtones[0],
504 'use': 'call' } ]
505
506
507 e[self.__pb_name]='"'+pb_entry['names'][0]['full']+'"'
508
509
510 secret='0'
511
512 try:
513 if pb_entry['flags'][0]['secret']:
514 secret='1'
515 except:
516 pass
517 e[self.__pb_secret]=secret
518
519
520
521 for k in range(len(self.__pb_numbers)):
522 for kk in self.__pb_numbers[k]:
523 e[self.__pb_numbers[k][kk]]=''
524 e[self.__pb_numbers[k][kk]+1]=''
525 speed_dial='0'
526 n=pb_entry.get('numbers', [])
527 for k in range(len(n)):
528 try:
529 nk=n[k]
530 kkk, kk=self._get_number_type(nk['type'])
531 except:
532
533 nk['type']='home'
534 kkk, kk=0, self.__pb_home_num
535 e[kk],e[kk+1]=self.phonize(nk['number']), secret
536 try:
537 if nk['speeddial']:
538 speed_dial=`kkk`
539 except:
540 pass
541
542 e[self.__pb_speed_dial]=speed_dial
543
544 email=''
545 try:
546 email=pb_entry['emails'][0]['email']
547 except:
548 pass
549 e[self.__pb_email]='"'+email+'"'
550 for k in self.__pb_blanks:
551 e[k]=''
552 e[self.__pb_date_time_stamp]=self.get_time_stamp()
553
554
555
556
557 ee=self.get_phone_entry(int(e[self.__pb_entry]))
558 if len(ee):
559
560
561 ee[self.__pb_name]='"'+ee[self.__pb_name]+'"'
562 ee[self.__pb_email]='"'+ee[self.__pb_email]+'"'
563 k=self.__pb_max_entries-2
564 if e[0:k]==ee[0:k]:
565 return True
566
567 return self.save_phone_entry('0,'+','.join(e))
568
569 getphoneinfo=com_samsung.Phone._getphoneinfo
570
571 getringtones=None
572
573 getwallpapers=None
574
575 getmedia=None
576
577 -class Profile(com_samsung.Profile):
578
579 serialsname='scha310'
580
581 phone_manufacturer='SAMSUNG ELECTRONICS'
582 phone_model='SCH-A310/148'
583
586
587 _supportedsyncs=(
588 ('phonebook', 'read', None),
589 ('phonebook', 'write', 'OVERWRITE'),
590 ('calendar', 'read', None),
591 ('calendar', 'write', 'OVERWRITE'),
592 )
593
597