#!/usr/bin/env python3 # # Scrape GATT UUIDs from Bluetooth SIG page # https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers # # Copyright 2017 BlueKitchen GmbH # from lxml import html import datetime import requests import sys import codecs import os import re import csv import getopt program_info = ''' BTstack Company ID Scraper for BTstack Copyright 2022, BlueKitchen GmbH ''' header = ''' /** * bluetooth_company_id.h generated from Bluetooth SIG website for BTstack by tool/bluetooth_company_id.py * {datetime} */ #ifndef BLUETOOTH_COMPANY_ID_H #define BLUETOOTH_COMPANY_ID_H ''' page_info = ''' /** * Assigned numbers from {page} */ ''' trailer = ''' #endif ''' tags = [] def strip_non_ascii(string): stripped = (c for c in string if 0 < ord(c) < 127) return ''.join(stripped) def create_name(company): # limit to ascii company = strip_non_ascii(company) # remove parts in braces p = re.compile('\(.*\)') tag = p.sub('',company).rstrip().upper() tag = tag.replace('&',' AND ') tag = tag.replace(''','') tag = tag.replace('"',' ') tag = tag.replace('+',' AND ') tag = tag.replace(' - ', ' ') tag = tag.replace('/', ' ') tag = tag.replace(';',' ') tag = tag.replace(',','') tag = tag.replace('.', '') tag = tag.replace('-','_') tag = tag.replace(' ',' ') tag = tag.replace(' ','_') tag = tag.replace('&','AND') tag = tag.replace("'","_") tag = tag.replace('"','_') tag = tag.replace('!','_') tag = tag.replace('|','_') tag = tag.replace('[','') tag = tag.replace(']','') return "BLUETOOTH_COMPANY_ID_" + tag def parse_cvs(csv_file): cvsreader = csv.reader(csv_file, delimiter=',', quotechar='\"') # Skip header ['"Decimal","Hexadecimal","Company"'] next(cvsreader) companies = {} for row in cvsreader: id_dec = int(row[0]) companies[id_dec] = (row[1],row[2]) return companies def write_cvs(fout, companies, url): global tags fout.write(page_info.format(page=url.replace('https://',''))) company_ids = sorted(list(companies.keys())) for id_dec in company_ids: id_hex = companies[id_dec][0] company = create_name(companies[id_dec][1]) if company in tags: company = company+"2" else: tags.append(company) fout.write("#define %-80s %s\n" % (company, id_hex)) # map CSR onto QTIL fout.write("#define BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO BLUETOOTH_COMPANY_ID_QUALCOMM_TECHNOLOGIES_INTERNATIONAL_LTD\n") def main(argv): url = "https://www.bluetooth.com/de/specifications/assigned-numbers/company-identifiers/#" btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') tools_root = btstack_root + '/tool' src_root = btstack_root + '/src/' header_filename = "bluetooth_company_id.h" header_path = btstack_root + "/src/" + header_filename cvs_filename = "CompanyIdentfiers - CSV.csv" cvs_path = tools_root + "/" + cvs_filename print(program_info) try: header_file = open(header_path, "w") except FileNotFoundError: print("\nFile \'%s\' cannot be created in \'%s\' directory." % (header_filename, src_root)) exit(1) try: with open(cvs_path, "r") as csv_file: companies = parse_cvs(csv_file) header_file.write(header.format(datetime=str(datetime.datetime.now()))) write_cvs(header_file, companies, url) header_file.write(trailer) print("Company IDs are stored in \'%s\'\n" % (header_path)) except FileNotFoundError: print("\nCVS file \'%s\' not found in \'%s\'." % (cvs_filename, tools_root)) print("Please download the CVS file, then start the skript again.\n") print("The CVS file can be downloaded from:") print(" %s\n" % url) exit(1) if __name__ == "__main__": main(sys.argv[1:])