<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>gammu</title>
  <link rel="alternate" type="text/html" href="http://tumbleweed.org.za/tags/gammu"/>
  <link rel="self" type="application/atom+xml" href="http://tumbleweed.org.za/taxonomy/term/180/atom/feed"/>
  <id>http://tumbleweed.org.za/taxonomy/term/180/atom/feed</id>
  <updated>2008-10-17T12:04:58+00:00</updated>
  <entry>
    <title>Gammu with Samsung</title>
    <link rel="alternate" type="text/html" href="http://tumbleweed.org.za/2008/04/29/gammu-samsung" />
    <id>http://tumbleweed.org.za/2008/04/29/gammu-samsung</id>
    <published>2008-04-29T20:33:29+00:00</published>
    <updated>2008-10-17T12:04:58+00:00</updated>
    <author>
      <name>tumbleweed</name>
    </author>
    <category term="cell-phone" />
    <category term="gammu" />
    <category term="python" />
    <category term="samsung" />
    <category term="technical" />
    <summary type="html"><![CDATA[<p>A housemate of mine got a new Samsung phone on the weekend. Being a resident geek, I offered to transfer her contacts across rather than get her sister to manually retype&nbsp;500-odd&nbsp;contacts.</p>

<p>Naturally, I thought this would be a simple problem, right? I mean, everyone updates their phones every 2 years, this must be a pretty common use case. All my Sony Ericsson phones have had a &#8220;send all contacts by Bluetooth&#8221; option since the inception of Bluetooth. Naturally, it didn&#8217;t have such a feature, it only supports sending one contact at a time. (Although, to Samsung&#8217;s credit, the <em>new</em> phone will be able to do for the&nbsp;next&nbsp;upgrade)</p>

<p>Next option: I&#8217;ll sync old phone to laptop to&nbsp;new&nbsp;phone.</p>

<p>The Samsung website has a helpful Windows utility that you can download to do this, however you need the cable to link the phone to the computer. The phones needed different cables, and I had neither. My laptop with a Windows partition has had broken Bluetooth ever since <a href="/2006/12/29/acer-laptop-woes-part-7">its motherboard got replaced</a>. So that wasn&#8217;t an option. The phones don&#8217;t have <span class="caps"><span class="caps">IRDA</span></span>, so there was no way to connect them with the&nbsp;Windows&nbsp;laptop.</p>

<p>Time to do&nbsp;it&nbsp;properly.</p>

<p>I tried <a href="http://wammu.eu/">wammu</a>, a python-based <a href="http://www.gammu.org/">gammu</a> <span class="caps"><span class="caps">GUI</span></span>. It supported the phones via the &#8220;blueat&#8221; driver, and could browse their <span class="caps"><span class="caps">SIM</span></span> cards fine, but not their internal Phonebooks. It couldn&#8217;t back them up either. A bit of poking around with gammu on the command line showed that the internal phone books are not 0-indexed (normal computer counting, 0 to n-1) or 1-indexed (normal human counting, 1 to n), but 2-indexed. Dijkstra would turn in&nbsp;his&nbsp;grave!</p>

<p>At this point, I could see that I was going to have to write my own, backup utility. The output of gammu was awkable, but seeing as there are good gammu-python bindings, I decided to do it in&nbsp;pure&nbsp;Python.</p>

<p>Reading the address book went something&nbsp;like&nbsp;this:</p>

<div class="geshifilter"><div class="python geshifilter-python" style="font-family:monospace;"><span class="kw1">import</span> gammu, <span class="kw3">pickle</span><br />
sm = gammu.<span class="me1">StateMachine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
sm.<span class="me1">ReadConfig</span><span class="br0">&#40;</span><span class="nu0">3</span>, <span class="nu0">0</span><span class="br0">&#41;</span><br />
sm.<span class="me1">Init</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
old = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">2</span>, <span class="nu0">587</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; old.<span class="me1">append</span><span class="br0">&#40;</span>sm.<span class="me1">GetMemory</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps"><span class="caps">ME</span></span>&quot;</span>, i<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<br />
<span class="kw3">pickle</span>.<span class="me1">dump</span><span class="br0">&#40;</span>old, <span class="kw2">file</span><span class="br0">&#40;</span><span class="st0">&quot;phonebook.dump&quot;</span>, <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></div>

<p>The 3 signifies gammu configuration number 3, read into position 0. 587 is the number of address book entries. &#8220;<span class="caps"><span class="caps">ME</span></span>&#8221; means internal memory. I then pickled &#8220;old&#8221; in preparation for the next stage. Here is an example of an item&nbsp;in&nbsp;old:</p>

<div class="geshifilter"><div class="python geshifilter-python" style="font-family:monospace;"><span class="br0">&#123;</span><span class="st0">&#8216;Entries&#8217;</span>: <span class="br0">&#91;</span><span class="br0">&#123;</span><span class="st0">&#8216;AddError&#8217;</span>: <span class="nu0">7517792</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Type&#8217;</span>: <span class="st0">&#8216;Text_FirstName&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Value&#8217;</span>: u<span class="st0">&#8216;Foo&#8217;</span><span class="br0">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><span class="st0">&#8216;AddError&#8217;</span>: <span class="nu0">796160623</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Type&#8217;</span>: <span class="st0">&#8216;Text_LastName&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Value&#8217;</span>: u<span class="st0">&#8216;Bar&#8217;</span><span class="br0">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><span class="st0">&#8216;AddError&#8217;</span>: <span class="nu0">796160623</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;SMSList&#8217;</span>: <span class="br0">&#91;</span><span class="br0">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Type&#8217;</span>: <span class="st0">&#8216;Number_Other&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Value&#8217;</span>: u<span class="st0">&#8216;0211234567&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;VoiceTag&#8217;</span>: <span class="nu0">0</span><span class="br0">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><span class="st0">&#8216;Type&#8217;</span>: <span class="st0">&#8216;Category&#8217;</span>, <span class="st0">&#8216;Value&#8217;</span>: <span class="nu0">0</span><span class="br0">&#125;</span><span class="br0">&#93;</span>,<br />
&nbsp;<span class="st0">&#8216;Location&#8217;</span>: <span class="nu0">2</span>,<br />
&nbsp;<span class="st0">&#8216;MemoryType&#8217;</span>: <span class="st0">&#8216;<span class="caps"><span class="caps">ME</span></span>&#8217;</span><span class="br0">&#125;</span></div></div>

<p>Pretty icky, but at least all the information is there. At this point, one should be able to feed it into the&nbsp;new&nbsp;phone:</p>

<div class="geshifilter"><div class="python geshifilter-python" style="font-family:monospace;">sm.<span class="me1">Terminate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
sm = gammu.<span class="me1">StateMachine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
sm.<span class="me1">ReadConfig</span><span class="br0">&#40;</span><span class="nu0">4</span>, <span class="nu0">0</span><span class="br0">&#41;</span><br />
sm.<span class="me1">Init</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> old:<br />
&nbsp; &nbsp; &nbsp; &nbsp; sm.<span class="me1">AddMemory</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span></div></div>

<p>However nothing I tried worked, I always got an &#8220;Invalid Location&#8221; error. I think the 2-indexing is trumping&nbsp;gammu&nbsp;again.</p>

<p>Next idea, lets munge the data into vCard format and use wammu / gammu&#8217;s &#8220;import from vCard&#8221; function. (Code coming up soon) Turns out this doesn&#8217;t work either. The phone only received the First name, first phone number, and various other things that I didn&#8217;t send it (i.e. custom ring tones that it made&nbsp;up).&nbsp;Hmph!</p>

<p>Aha, but cellphones can normally Bluetooth vCards to each other. So I pushed it the vCard collection via obexftp. Starts transmitting, but then the phone reboots. I played around a bit, and found that if you send it more than one vCard in a vCard file, it&nbsp;reboots.&nbsp;Lovely.</p>

<p>So my final solution was: Extract address book with python-gammu. Transform into vCards. Send each one individually. At least the phone had a &#8220;trust this device&#8221; option so that it wouldn&#8217;t prompt the user for every vCard I sent, but just automatically import them - the first sensible feature I&#8217;ve found&nbsp;on&nbsp;it.</p>

<p>Here&nbsp;goes:</p>

<div class="geshifilter"><div class="python geshifilter-python" style="font-family:monospace;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="kw1">import</span> <span class="kw3">os</span>, <span class="kw3">pickle</span>, <span class="kw3">time</span><br />
<br />
<span class="kw1">def</span> normalise_num<span class="br0">&#40;</span>n<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Neaten up the phone number, internationalise, etc.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> n.<span class="me1">startswith</span><span class="br0">&#40;</span><span class="st0">&quot;+&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> n<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> n.<span class="me1">startswith</span><span class="br0">&#40;</span><span class="st0">&quot;00&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="st0">&quot;+&quot;</span> + n<span class="br0">&#91;</span><span class="nu0">2</span>:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span> == <span class="nu0">10</span> <span class="kw1">and</span> n<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;0&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="st0">&quot;+27&quot;</span> + n<span class="br0">&#91;</span><span class="nu0">1</span>:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> n<br />
<br />
d = <span class="kw3">pickle</span>.<span class="me1">load</span><span class="br0">&#40;</span><span class="kw2">file</span><span class="br0">&#40;</span><span class="st0">&quot;phonebook.dump&quot;</span>, <span class="st0">&quot;r&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<br />
<span class="co1"># Normalise into a sensible format:</span><br />
o = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> d:<br />
&nbsp; &nbsp; &nbsp; &nbsp; t = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> j <span class="kw1">in</span> i<span class="br0">&#91;</span><span class="st0">&quot;Entries&quot;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> j<span class="br0">&#91;</span><span class="st0">&quot;Type&quot;</span><span class="br0">&#93;</span> == <span class="st0">&quot;Text_FirstName&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span><span class="st0">&quot;First&quot;</span><span class="br0">&#93;</span> = j<span class="br0">&#91;</span><span class="st0">&quot;Value&quot;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> j<span class="br0">&#91;</span><span class="st0">&quot;Type&quot;</span><span class="br0">&#93;</span> == <span class="st0">&quot;Text_LastName&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span><span class="st0">&quot;Last&quot;</span><span class="br0">&#93;</span> = j<span class="br0">&#91;</span><span class="st0">&quot;Value&quot;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> j<span class="br0">&#91;</span><span class="st0">&quot;Type&quot;</span><span class="br0">&#93;</span> == <span class="st0">&quot;Number_Other&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n = normalise_num<span class="br0">&#40;</span>j<span class="br0">&#91;</span><span class="st0">&quot;Value&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">type</span> = <span class="st0">&quot;Home&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> n<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span> <span class="kw1">in</span> <span class="br0">&#40;</span><span class="st0">&quot;7&quot;</span>, <span class="st0">&quot;8&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">type</span> = <span class="st0">&quot;Cell&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">type</span> <span class="kw1">not</span> <span class="kw1">in</span> t:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span><span class="kw2">type</span><span class="br0">&#93;</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span><span class="kw2">type</span><span class="br0">&#93;</span>.<span class="me1">append</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; o.<span class="me1">append</span><span class="br0">&#40;</span>t<span class="br0">&#41;</span><br />
<br />
<span class="co1"># Write <span class="amp">&amp;</span> Send vCards:</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> o:<br />
&nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">file</span><span class="br0">&#40;</span><span class="st0">&quot;temp.vcf&quot;</span>, <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps"><span class="caps">BEGIN</span></span>:<span class="caps"><span class="caps">VCARD</span></span><span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps"><span class="caps">VERSION</span></span>:2.1<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;N:%s;%s;;;<span class="es0">\n</span>&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>i.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;Last&quot;</span>, <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span>, i.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;First&quot;</span>, <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; pref = <span class="st0">&quot;;<span class="caps"><span class="caps">PREF</span></span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> j <span class="kw1">in</span> i<span class="br0">&#91;</span><span class="st0">&quot;Cell&quot;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps"><span class="caps">TEL</span></span>;<span class="caps"><span class="caps">CELL</span></span>%s:%s<span class="es0">\n</span>&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>pref, j<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pref=<span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> j <span class="kw1">in</span> i<span class="br0">&#91;</span><span class="st0">&quot;Home&quot;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps"><span class="caps">TEL</span></span>;<span class="caps"><span class="caps">HOME</span></span>%s:%s<span class="es0">\n</span>&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>pref, j<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pref=<span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps"><span class="caps">END</span></span>:<span class="caps"><span class="caps">VCARD</span></span><span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">system</span><span class="br0">&#40;</span><span class="st0">&quot;obexftp -b 00:<span class="caps"><span class="caps">DE</span></span>:<span class="caps"><span class="caps">AD</span></span>:00:<span class="caps"><span class="caps">BE</span></span>:<span class="caps"><span class="caps">EF</span></span> -p temp.vcf&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Give the thing a chance to recover:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">time</span>.<span class="me1">sleep</span><span class="br0">&#40;</span><span class="nu0">0.1</span><span class="br0">&#41;</span></div></div>

<p>Yes, the normalisation could be done with list comprehensions, but it would be horrible to read. And there might by Python Obex bindings, but I couldn&#8217;t&nbsp;be&nbsp;bothered.</p>

<p>I got to spend an afternoon messing with dodgy Cellphones, rather than having a teenager do the job for free. I think I chose the wrong option, but at least it&nbsp;was&nbsp;fun.</p>

<p>Footnote: Samsung, your phones User Interface is <em>awful</em>. Why on earth is Bluetooth under &#8220;Applications&#8221; rather than &#8220;Settings&#8221;? I searched everywhere but there, and finally googled before I&nbsp;found&nbsp;it&#8230;</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>A housemate of mine got a new Samsung phone on the weekend. Being a resident geek, I offered to transfer her contacts across rather than get her sister to manually retype 500-odd&nbsp;contacts.</p>

<p>Naturally, I thought this would be a simple problem, right? I mean, everyone updates their phones every 2 years, this must be a pretty common use case. All my Sony Ericsson phones have had a &#8220;send all contacts by Bluetooth&#8221; option since the inception of Bluetooth. Naturally, it didn&#8217;t have such a feature, it only supports sending one contact at a time. (Although, to Samsung&#8217;s credit, the <em>new</em> phone will be able to do for the next&nbsp;upgrade)</p>

<p>Next option: I&#8217;ll sync old phone to laptop to new&nbsp;phone.</p>

<p>The Samsung website has a helpful Windows utility that you can download to do this, however you need the cable to link the phone to the computer. The phones needed different cables, and I had neither. My laptop with a Windows partition has had broken Bluetooth ever since <a href="/2006/12/29/acer-laptop-woes-part-7">its motherboard got replaced</a>. So that wasn&#8217;t an option. The phones don&#8217;t have <span class="caps">IRDA</span>, so there was no way to connect them with the Windows&nbsp;laptop.</p>

<p>Time to do it&nbsp;properly.</p>

<p>I tried <a href="http://wammu.eu/">wammu</a>, a python-based <a href="http://www.gammu.org/">gammu</a> <span class="caps">GUI</span>. It supported the phones via the &#8220;blueat&#8221; driver, and could browse their <span class="caps">SIM</span> cards fine, but not their internal Phonebooks. It couldn&#8217;t back them up either. A bit of poking around with gammu on the command line showed that the internal phone books are not 0-indexed (normal computer counting, 0 to n-1) or 1-indexed (normal human counting, 1 to n), but 2-indexed. Dijkstra would turn in his&nbsp;grave!</p>

<p>At this point, I could see that I was going to have to write my own, backup utility. The output of gammu was awkable, but seeing as there are good gammu-python bindings, I decided to do it in pure&nbsp;Python.</p>

<p>Reading the address book went something like&nbsp;this:</p>

<div class="geshifilter"><div class="python geshifilter-python" style="font-family:monospace;"><span class="kw1">import</span> gammu, <span class="kw3">pickle</span><br />
sm = gammu.<span class="me1">StateMachine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
sm.<span class="me1">ReadConfig</span><span class="br0">&#40;</span><span class="nu0">3</span>, <span class="nu0">0</span><span class="br0">&#41;</span><br />
sm.<span class="me1">Init</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
old = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">2</span>, <span class="nu0">587</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; old.<span class="me1">append</span><span class="br0">&#40;</span>sm.<span class="me1">GetMemory</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps">ME</span>&quot;</span>, i<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<br />
<span class="kw3">pickle</span>.<span class="me1">dump</span><span class="br0">&#40;</span>old, <span class="kw2">file</span><span class="br0">&#40;</span><span class="st0">&quot;phonebook.dump&quot;</span>, <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></div>

<p>The 3 signifies gammu configuration number 3, read into position 0. 587 is the number of address book entries. &#8220;<span class="caps">ME</span>&#8221; means internal memory. I then pickled &#8220;old&#8221; in preparation for the next stage. Here is an example of an item in&nbsp;old:</p>

<div class="geshifilter"><div class="python geshifilter-python" style="font-family:monospace;"><span class="br0">&#123;</span><span class="st0">&#8216;Entries&#8217;</span>: <span class="br0">&#91;</span><span class="br0">&#123;</span><span class="st0">&#8216;AddError&#8217;</span>: <span class="nu0">7517792</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Type&#8217;</span>: <span class="st0">&#8216;Text_FirstName&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Value&#8217;</span>: u<span class="st0">&#8216;Foo&#8217;</span><span class="br0">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><span class="st0">&#8216;AddError&#8217;</span>: <span class="nu0">796160623</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Type&#8217;</span>: <span class="st0">&#8216;Text_LastName&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Value&#8217;</span>: u<span class="st0">&#8216;Bar&#8217;</span><span class="br0">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><span class="st0">&#8216;AddError&#8217;</span>: <span class="nu0">796160623</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;SMSList&#8217;</span>: <span class="br0">&#91;</span><span class="br0">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Type&#8217;</span>: <span class="st0">&#8216;Number_Other&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Value&#8217;</span>: u<span class="st0">&#8216;0211234567&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;VoiceTag&#8217;</span>: <span class="nu0">0</span><span class="br0">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><span class="st0">&#8216;Type&#8217;</span>: <span class="st0">&#8216;Category&#8217;</span>, <span class="st0">&#8216;Value&#8217;</span>: <span class="nu0">0</span><span class="br0">&#125;</span><span class="br0">&#93;</span>,<br />
&nbsp;<span class="st0">&#8216;Location&#8217;</span>: <span class="nu0">2</span>,<br />
&nbsp;<span class="st0">&#8216;MemoryType&#8217;</span>: <span class="st0">&#8216;<span class="caps">ME</span>&#8217;</span><span class="br0">&#125;</span></div></div>

<p>Pretty icky, but at least all the information is there. At this point, one should be able to feed it into the new&nbsp;phone:</p>

<div class="geshifilter"><div class="python geshifilter-python" style="font-family:monospace;">sm.<span class="me1">Terminate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
sm = gammu.<span class="me1">StateMachine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
sm.<span class="me1">ReadConfig</span><span class="br0">&#40;</span><span class="nu0">4</span>, <span class="nu0">0</span><span class="br0">&#41;</span><br />
sm.<span class="me1">Init</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> old:<br />
&nbsp; &nbsp; &nbsp; &nbsp; sm.<span class="me1">AddMemory</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span></div></div>

<p>However nothing I tried worked, I always got an &#8220;Invalid Location&#8221; error. I think the 2-indexing is trumping gammu&nbsp;again.</p>

<p>Next idea, lets munge the data into vCard format and use wammu / gammu&#8217;s &#8220;import from vCard&#8221; function. (Code coming up soon) Turns out this doesn&#8217;t work either. The phone only received the First name, first phone number, and various other things that I didn&#8217;t send it (i.e. custom ring tones that it made up).&nbsp;Hmph!</p>

<p>Aha, but cellphones can normally Bluetooth vCards to each other. So I pushed it the vCard collection via obexftp. Starts transmitting, but then the phone reboots. I played around a bit, and found that if you send it more than one vCard in a vCard file, it reboots.&nbsp;Lovely.</p>

<p>So my final solution was: Extract address book with python-gammu. Transform into vCards. Send each one individually. At least the phone had a &#8220;trust this device&#8221; option so that it wouldn&#8217;t prompt the user for every vCard I sent, but just automatically import them - the first sensible feature I&#8217;ve found on&nbsp;it.</p>

<p>Here&nbsp;goes:</p>

<div class="geshifilter"><div class="python geshifilter-python" style="font-family:monospace;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="kw1">import</span> <span class="kw3">os</span>, <span class="kw3">pickle</span>, <span class="kw3">time</span><br />
<br />
<span class="kw1">def</span> normalise_num<span class="br0">&#40;</span>n<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Neaten up the phone number, internationalise, etc.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> n.<span class="me1">startswith</span><span class="br0">&#40;</span><span class="st0">&quot;+&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> n<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> n.<span class="me1">startswith</span><span class="br0">&#40;</span><span class="st0">&quot;00&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="st0">&quot;+&quot;</span> + n<span class="br0">&#91;</span><span class="nu0">2</span>:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span> == <span class="nu0">10</span> <span class="kw1">and</span> n<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;0&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="st0">&quot;+27&quot;</span> + n<span class="br0">&#91;</span><span class="nu0">1</span>:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> n<br />
<br />
d = <span class="kw3">pickle</span>.<span class="me1">load</span><span class="br0">&#40;</span><span class="kw2">file</span><span class="br0">&#40;</span><span class="st0">&quot;phonebook.dump&quot;</span>, <span class="st0">&quot;r&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<br />
<span class="co1"># Normalise into a sensible format:</span><br />
o = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> d:<br />
&nbsp; &nbsp; &nbsp; &nbsp; t = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> j <span class="kw1">in</span> i<span class="br0">&#91;</span><span class="st0">&quot;Entries&quot;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> j<span class="br0">&#91;</span><span class="st0">&quot;Type&quot;</span><span class="br0">&#93;</span> == <span class="st0">&quot;Text_FirstName&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span><span class="st0">&quot;First&quot;</span><span class="br0">&#93;</span> = j<span class="br0">&#91;</span><span class="st0">&quot;Value&quot;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> j<span class="br0">&#91;</span><span class="st0">&quot;Type&quot;</span><span class="br0">&#93;</span> == <span class="st0">&quot;Text_LastName&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span><span class="st0">&quot;Last&quot;</span><span class="br0">&#93;</span> = j<span class="br0">&#91;</span><span class="st0">&quot;Value&quot;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> j<span class="br0">&#91;</span><span class="st0">&quot;Type&quot;</span><span class="br0">&#93;</span> == <span class="st0">&quot;Number_Other&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n = normalise_num<span class="br0">&#40;</span>j<span class="br0">&#91;</span><span class="st0">&quot;Value&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">type</span> = <span class="st0">&quot;Home&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> n<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span> <span class="kw1">in</span> <span class="br0">&#40;</span><span class="st0">&quot;7&quot;</span>, <span class="st0">&quot;8&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">type</span> = <span class="st0">&quot;Cell&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">type</span> <span class="kw1">not</span> <span class="kw1">in</span> t:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span><span class="kw2">type</span><span class="br0">&#93;</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span><span class="kw2">type</span><span class="br0">&#93;</span>.<span class="me1">append</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; o.<span class="me1">append</span><span class="br0">&#40;</span>t<span class="br0">&#41;</span><br />
<br />
<span class="co1"># Write <span class="amp">&amp;</span> Send vCards:</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> o:<br />
&nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">file</span><span class="br0">&#40;</span><span class="st0">&quot;temp.vcf&quot;</span>, <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps">BEGIN</span>:<span class="caps">VCARD</span><span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps">VERSION</span>:2.1<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;N:%s;%s;;;<span class="es0">\n</span>&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>i.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;Last&quot;</span>, <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span>, i.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;First&quot;</span>, <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; pref = <span class="st0">&quot;;<span class="caps">PREF</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> j <span class="kw1">in</span> i<span class="br0">&#91;</span><span class="st0">&quot;Cell&quot;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps">TEL</span>;<span class="caps">CELL</span>%s:%s<span class="es0">\n</span>&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>pref, j<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pref=<span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> j <span class="kw1">in</span> i<span class="br0">&#91;</span><span class="st0">&quot;Home&quot;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps">TEL</span>;<span class="caps">HOME</span>%s:%s<span class="es0">\n</span>&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>pref, j<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pref=<span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="caps">END</span>:<span class="caps">VCARD</span><span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">system</span><span class="br0">&#40;</span><span class="st0">&quot;obexftp -b 00:<span class="caps">DE</span>:<span class="caps">AD</span>:00:<span class="caps">BE</span>:<span class="caps">EF</span> -p temp.vcf&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Give the thing a chance to recover:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">time</span>.<span class="me1">sleep</span><span class="br0">&#40;</span><span class="nu0">0.1</span><span class="br0">&#41;</span></div></div>

<p>Yes, the normalisation could be done with list comprehensions, but it would be horrible to read. And there might by Python Obex bindings, but I couldn&#8217;t be&nbsp;bothered.</p>

<p>I got to spend an afternoon messing with dodgy Cellphones, rather than having a teenager do the job for free. I think I chose the wrong option, but at least it was&nbsp;fun.</p>

<p>Footnote: Samsung, your phones User Interface is <em>awful</em>. Why on earth is Bluetooth under &#8220;Applications&#8221; rather than &#8220;Settings&#8221;? I searched everywhere but there, and finally googled before I found&nbsp;it&#8230;</p>
    ]]></content>
  </entry>
</feed>
