xref: /btstack/tool/bluetooth_company_id.py (revision 77bd03813f180d723705f07c568f73ec226e388e)
1#!/usr/bin/env python3
2#
3# Scrape GATT UUIDs from Bluetooth SIG page
4# https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
5#
6# Copyright 2017 BlueKitchen GmbH
7#
8
9from lxml import html
10import datetime
11import requests
12import sys
13import codecs
14import os
15import re
16
17import csv
18import getopt
19
20
21program_info = '''
22BTstack Company ID Scraper for BTstack
23Copyright 2022, BlueKitchen GmbH
24'''
25
26header = '''
27/**
28 * bluetooth_company_id.h generated from Bluetooth SIG website for BTstack by tool/bluetooth_company_id.py
29 * {datetime}
30 */
31
32#ifndef BLUETOOTH_COMPANY_ID_H
33#define BLUETOOTH_COMPANY_ID_H
34'''
35
36page_info = '''
37/**
38 * Assigned numbers from {page}
39 */
40'''
41
42trailer = '''
43#endif
44'''
45
46tags = []
47
48def strip_non_ascii(string):
49    stripped = (c for c in string if 0 < ord(c) < 127)
50    return ''.join(stripped)
51
52def create_name(company):
53    # limit to ascii
54    company = strip_non_ascii(company)
55    # remove parts in braces
56    p = re.compile('\(.*\)')
57    tag = p.sub('',company).rstrip().upper()
58    tag = tag.replace('&AMP;',' AND ')
59    tag = tag.replace('&#39;','')
60    tag = tag.replace('&QUOT;',' ')
61    tag = tag.replace('+',' AND ')
62    tag = tag.replace(' - ', ' ')
63    tag = tag.replace('/', ' ')
64    tag = tag.replace(';',' ')
65    tag = tag.replace(',','')
66    tag = tag.replace('.', '')
67    tag = tag.replace('-','_')
68    tag = tag.replace('  ',' ')
69    tag = tag.replace(' ','_')
70    tag = tag.replace('&','AND')
71    tag = tag.replace("'","_")
72    tag = tag.replace('"','_')
73    tag = tag.replace('!','_')
74    tag = tag.replace('|','_')
75    tag = tag.replace('[','')
76    tag = tag.replace(']','')
77    return "BLUETOOTH_COMPANY_ID_" + tag
78
79def parse_cvs(csv_file):
80    cvsreader = csv.reader(csv_file, delimiter=',', quotechar='\"')
81    # Skip header ['"Decimal","Hexadecimal","Company"']
82    next(cvsreader)
83
84    companies = {}
85    for row in cvsreader:
86        id_dec = int(row[0])
87        companies[id_dec] = (row[1],row[2])
88    return companies
89
90
91def write_cvs(fout, companies, url):
92    global tags
93    fout.write(page_info.format(page=url.replace('https://','')))
94
95    company_ids = sorted(list(companies.keys()))
96
97    for id_dec in company_ids:
98        id_hex = companies[id_dec][0]
99        company = create_name(companies[id_dec][1])
100
101        if company in tags:
102            company = company+"2"
103        else:
104            tags.append(company)
105
106        fout.write("#define %-80s %s\n" %  (company, id_hex))
107
108    # map CSR onto QTIL
109    fout.write("#define BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO BLUETOOTH_COMPANY_ID_QUALCOMM_TECHNOLOGIES_INTERNATIONAL_LTD\n")
110
111def main(argv):
112    url = "https://www.bluetooth.com/de/specifications/assigned-numbers/company-identifiers/#"
113    btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..')
114    tools_root = btstack_root + '/tool'
115    src_root   = btstack_root + '/src/'
116
117    header_filename = "bluetooth_company_id.h"
118    header_path = btstack_root + "/src/" + header_filename
119
120    cvs_filename = "CompanyIdentfiers - CSV.csv"
121    cvs_path = tools_root + "/" + cvs_filename
122
123    print(program_info)
124
125    try:
126        header_file = open(header_path, "w")
127    except FileNotFoundError:
128        print("\nFile \'%s\' cannot be created in \'%s\' directory." % (header_filename, src_root))
129        exit(1)
130
131    try:
132        with open(cvs_path, "r") as csv_file:
133            companies = parse_cvs(csv_file)
134
135            header_file.write(header.format(datetime=str(datetime.datetime.now())))
136            write_cvs(header_file, companies, url)
137            header_file.write(trailer)
138
139            print("Company IDs are stored in \'%s\'\n" % (header_path))
140    except FileNotFoundError:
141        print("\nCVS file \'%s\' not found in \'%s\'." % (cvs_filename, tools_root))
142        print("Please download the CVS file, then start the skript again.\n")
143        print("The CVS file can be downloaded from:")
144        print("     %s\n" % url)
145        exit(1)
146
147if __name__ == "__main__":
148   main(sys.argv[1:])
149
150
151