CardDav zu Grandstream XML

Tobias Bauer, , Lesedauer 3 Minuten.

Für die Telefonie nutze ich seit neuesten Grandstream GXP2130 VoIP Telefone. Leider gibt es nur eine Anbindung per LDAB an eine zentrale Adressbuchlösung. Für CardDAV, wie diese nutze, ist dies leider nicht möglich. Hier muss man auf das lokale Adressbuch zurückgreifen.

Als Lösung gibt es jedoch die Möglichkeit, dieses ber eine XML-Datei zu ex- und importieren. Bei der Suche im Internet bin ich hier auf ein Python-Gist-Skript von Tobias Senger gestoßen, welches eine VCF-Datei in das entsprechende XML-Format konvertiert. Das ist für mich ein guter Ausgangspunkt gewesen.

Das CardDav-Adressbuch binde ich per CardBook in Thunderbird ein. Dort kann man das mit einem Rechtsklick auf das Adressbuch exportieren und als VCF-Datei speichern. Das Skript erwartet den Namen „contacts.vcf“, weshalb man die Datei gleich so bennen sollte.

Ich nutze bei mir die Funktion, das bestimmte Rufnummern (Favouriten) durch die DND-Funktion durch rufen dürfen. Ich habe dies nun so gelöst, dass Personen, welche in bestimmten Kategorien/Gruppen enthalten sind, diese Freischaltung erhalten. Auch habe ich in meinem Adressbuch Firmenkontakte und möchte hier gerne die Firma mit in die XML-Datei übernehmen. Aus diesem Grund habe ich einen Fork angelegt und das Skript erweitert.

#Convert CardDav contacts to GrandStream DP720 / DP750 XML phonebook

import vobject

vcf_path = "./contacts.vcf"
xml_path = './xml_contacts.xml'

# phone number: CardDav to Grandstream
map_number_types = {
    "work":   "Work",
    "home":   "Home",
    "main":   "Home",
    "cell":   "Mobile",
    "other":  "Home",
    "voice":  "Home",
    "mobile": "Mobile"
}
# categories: CardDav to Favorite
map_frequent_categories = {
    "frequent": "1",
    "vip"   :   "1",
    "familie":  "1"
}

input_counter = 0
output_counter = 0

with open(vcf_path, 'r') as f:
    vcards = vobject.readComponents(f.read())
    
    out_file = open(xml_path,'w')
    out_file.write('<?xml version="1.0" encoding="UTF-8"?>')
    out_file.write('<AddressBook><version>1</version>')
    
    for vcard in vcards:
        # init
        company = ""
        frequent = "0"

        input_counter += 1
        
        numbers = []
        
        for p in vcard.getChildren():
            if p.name == "N":
                givenname = p.value.given
                familyname = p.value.family

            if p.name == "ORG":
                company = ""
                org_counter = 0
                while org_counter < len(p.value):
                    if org_counter > 0:
                        company = company + " / "
                    company = company + p.value[org_counter]
                    org_counter += 1
            
            if p.name == "TEL":
                itype = p.type_param.lower()
                if not itype in map_number_types:
                    if not itype in ["pref"]:
                        print("Warning: Unknown type: '%s'" % (itype))
                    continue
                ntype = map_number_types[itype]
                
                t = ntype, p.value.replace(' ', '')
                numbers.append(t)

            if p.name == "CATEGORIES":
                cats = p.value[0].split(",")
                cat_counter = 0
                while cat_counter < len(cats):
                    if cats[cat_counter].lower() in map_frequent_categories:
                        frequent = "1"
                        break
                    cat_counter += 1
        
        if len(numbers)>0:
            output_counter += 1
        
            out_file.write('<Contact>')
            out_file.write('<FirstName>'+givenname+'</FirstName>')
            out_file.write('<LastName>'+familyname+'</LastName>')
            out_file.write('<Ringtone>0</Ringtone>') 
        
            for n in numbers:
                ntype, value = n
                out_file.write('<Phone type="'+ntype+'">')
                out_file.write('<phonenumber>'+value+'</phonenumber>')
                out_file.write('</Phone>')

            out_file.write('<Frequent>'+frequent+'</Frequent>')

            if company:
                out_file.write('<Company>'+company+'</Company>')
    
            out_file.write('</Contact>')
            
    out_file.write('</AddressBook>')
    out_file.close
    
print ("DONE!")
print ("Processed %s input contacts. %s contacts contained phone numbers and where exported into XML file: %s" % (input_counter, output_counter, out_file.name))

Ist ein Python-Interpreter installiert kann man die Konvertierung einfach starten. Unter Linux schaut der Aufruf wie folgt aus:

python ./pfad/zum/Script/CardDav2GrandstreamXML.py

Der Aufruf muss in dem Verzeichnis erfolgen, in dem die „contacts.vcf“ liegt. Man erhält dann eine Ausgabe, wenn zusätzliche, unbekannte Rufnummerntypen gefunden werden (bei mir waren das vor allem Fax-Nummern) sowie eine Zusammenfassung, wie viele Kontakte in die XML-Datei übernommen wurden.

Die erzeugt „xml_contacts.xml“ kann dann ganz einfach in die Grandstream Telefone über das Webinterface übernommen werden.