1#!/usr/bin/env python3 2# 3# Scrape GATT UUIDs from Bluetooth SIG page 4# Copyright 2016 BlueKitchen GmbH 5# 6 7from lxml import html 8import datetime 9import requests 10import sys 11import os 12 13headers = {'user-agent': 'curl/7.63.0'} 14 15program_info = ''' 16BTstack GATT UUID Scraper for BTstack 17Copyright 2016, BlueKitchen GmbH 18''' 19 20header = ''' 21/** 22 * bluetooth_gatt.h generated from Bluetooth SIG website for BTstack tool/bluetooth_gatt.py 23 * {datetime} 24 */ 25 26#ifndef BLUETOOTH_GATT_H 27#define BLUETOOTH_GATT_H 28''' 29 30page_info = ''' 31/** 32 * Assigned numbers from {page} 33 */ 34''' 35 36trailer = ''' 37#endif 38''' 39 40def strip_non_ascii(string): 41 stripped = (c for c in string if 0 < ord(c) < 127) 42 return ''.join(stripped) 43 44def scrape_page(fout, url): 45 print("Parsing %s" % url) 46 fout.write(page_info.format(page=url.replace('https://',''))) 47 page = requests.get(url, headers=headers) 48 tree = html.fromstring(page.content) 49 # get all <tr> elements in <table> 50 rows = tree.xpath('//table/tbody/tr') 51 for row in rows: 52 children = row.getchildren() 53 summary = strip_non_ascii(children[0].text_content()) 54 id = children[1].text_content() 55 # fix unexpected suffix _ 56 id = id.replace('.gatt_.', '.gatt.') 57 uuid = children[2].text_content() 58 if (len(id)): 59 tag = id.upper().replace('.', '_').replace('-','_') 60 fout.write("#define %-80s %s // %s\n" % (tag, uuid, summary)) 61 62btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 63gen_path = btstack_root + '/src/bluetooth_gatt.h' 64 65print(program_info) 66 67with open(gen_path, 'wt') as fout: 68 fout.write(header.format(datetime=str(datetime.datetime.now()))) 69 scrape_page(fout, 'https://www.bluetooth.com/specifications/gatt/declarations') 70 scrape_page(fout, 'https://www.bluetooth.com/specifications/gatt/services') 71 scrape_page(fout, 'https://www.bluetooth.com/specifications/gatt/characteristics') 72 scrape_page(fout, 'https://www.bluetooth.com/specifications/gatt/descriptors') 73 fout.write("// START(manually added, missing on Bluetooth Website\n") 74 fout.write("#define %-80s %s // %s\n" % ("ORG_BLUETOOTH_CHARACTERISTIC_MESH_PROVISIONING_DATA_IN" , "0x2ADB", '')) 75 fout.write("#define %-80s %s // %s\n" % ("ORG_BLUETOOTH_CHARACTERISTIC_MESH_PROVISIONING_DATA_OUT", "0x2ADC", '')) 76 fout.write("#define %-80s %s // %s\n" % ("ORG_BLUETOOTH_CHARACTERISTIC_MESH_PROXY_DATA_IN" , "0x2ADD", '')) 77 fout.write("#define %-80s %s // %s\n" % ("ORG_BLUETOOTH_CHARACTERISTIC_MESH_PROXY_DATA_OUT" , "0x2ADE", '')) 78 fout.write("// END(manualy added, missing on Bluetooth Website\n") 79 fout.write(trailer) 80 81print('Scraping successful!\n') 82