1*5c544019SMatthias Ringwald#!/usr/bin/env python3 20e0e9559SMatthias Ringwald# 30e0e9559SMatthias Ringwald# Scrape GATT UUIDs from Bluetooth SIG page 40e0e9559SMatthias Ringwald# Copyright 2016 BlueKitchen GmbH 50e0e9559SMatthias Ringwald# 60e0e9559SMatthias Ringwald 70e0e9559SMatthias Ringwaldfrom lxml import html 80e0e9559SMatthias Ringwaldimport datetime 90e0e9559SMatthias Ringwaldimport requests 100e0e9559SMatthias Ringwaldimport sys 110e0e9559SMatthias Ringwaldimport os 120e0e9559SMatthias Ringwald 130d9cb02cSMatthias Ringwaldheaders = {'user-agent': 'curl/7.63.0'} 140d9cb02cSMatthias Ringwald 150e0e9559SMatthias Ringwaldprogram_info = ''' 160e0e9559SMatthias RingwaldBTstack GATT UUID Scraper for BTstack 170e0e9559SMatthias RingwaldCopyright 2016, BlueKitchen GmbH 180e0e9559SMatthias Ringwald''' 190e0e9559SMatthias Ringwald 200e0e9559SMatthias Ringwaldheader = ''' 210e0e9559SMatthias Ringwald/** 22b436f177SMatthias Ringwald * bluetooth_gatt.h generated from Bluetooth SIG website for BTstack tool/bluetooth_gatt.py 23b436f177SMatthias Ringwald * {datetime} 240e0e9559SMatthias Ringwald */ 250e0e9559SMatthias Ringwald 2680e33422SMatthias Ringwald#ifndef BLUETOOTH_GATT_H 2780e33422SMatthias Ringwald#define BLUETOOTH_GATT_H 280e0e9559SMatthias Ringwald''' 290e0e9559SMatthias Ringwald 300e0e9559SMatthias Ringwaldpage_info = ''' 310e0e9559SMatthias Ringwald/** 320e0e9559SMatthias Ringwald * Assigned numbers from {page} 330e0e9559SMatthias Ringwald */ 340e0e9559SMatthias Ringwald''' 350e0e9559SMatthias Ringwald 360e0e9559SMatthias Ringwaldtrailer = ''' 370e0e9559SMatthias Ringwald#endif 380e0e9559SMatthias Ringwald''' 390e0e9559SMatthias Ringwald 400d9cb02cSMatthias Ringwalddef strip_non_ascii(string): 410d9cb02cSMatthias Ringwald stripped = (c for c in string if 0 < ord(c) < 127) 420d9cb02cSMatthias Ringwald return ''.join(stripped) 430d9cb02cSMatthias Ringwald 440e0e9559SMatthias Ringwalddef scrape_page(fout, url): 450e0e9559SMatthias Ringwald print("Parsing %s" % url) 46d918542bSMatthias Ringwald fout.write(page_info.format(page=url.replace('https://',''))) 470d9cb02cSMatthias Ringwald page = requests.get(url, headers=headers) 480e0e9559SMatthias Ringwald tree = html.fromstring(page.content) 490d9cb02cSMatthias Ringwald # get all <tr> elements in <table> 500d9cb02cSMatthias Ringwald rows = tree.xpath('//table/tbody/tr') 510e0e9559SMatthias Ringwald for row in rows: 520e0e9559SMatthias Ringwald children = row.getchildren() 530d9cb02cSMatthias Ringwald summary = strip_non_ascii(children[0].text_content()) 540e0e9559SMatthias Ringwald id = children[1].text_content() 550d9cb02cSMatthias Ringwald # fix unexpected suffix _ 560d9cb02cSMatthias Ringwald id = id.replace('.gatt_.', '.gatt.') 570e0e9559SMatthias Ringwald uuid = children[2].text_content() 580e0e9559SMatthias Ringwald if (len(id)): 5966fd3432SMatthias Ringwald tag = id.upper().replace('.', '_').replace('-','_') 6066fd3432SMatthias Ringwald fout.write("#define %-80s %s // %s\n" % (tag, uuid, summary)) 610e0e9559SMatthias Ringwald 620e0e9559SMatthias Ringwaldbtstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 630e0e9559SMatthias Ringwaldgen_path = btstack_root + '/src/bluetooth_gatt.h' 640e0e9559SMatthias Ringwald 650e0e9559SMatthias Ringwaldprint(program_info) 660e0e9559SMatthias Ringwald 670e0e9559SMatthias Ringwaldwith open(gen_path, 'wt') as fout: 680e0e9559SMatthias Ringwald fout.write(header.format(datetime=str(datetime.datetime.now()))) 690e0e9559SMatthias Ringwald scrape_page(fout, 'https://www.bluetooth.com/specifications/gatt/declarations') 700e0e9559SMatthias Ringwald scrape_page(fout, 'https://www.bluetooth.com/specifications/gatt/services') 710e0e9559SMatthias Ringwald scrape_page(fout, 'https://www.bluetooth.com/specifications/gatt/characteristics') 720e0e9559SMatthias Ringwald scrape_page(fout, 'https://www.bluetooth.com/specifications/gatt/descriptors') 7336d972adSMilanka Ringwald fout.write("// START(manually added, missing on Bluetooth Website\n") 7436d972adSMilanka Ringwald fout.write("#define %-80s %s // %s\n" % ("ORG_BLUETOOTH_CHARACTERISTIC_MESH_PROVISIONING_DATA_IN" , "0x2ADB", '')) 7536d972adSMilanka Ringwald fout.write("#define %-80s %s // %s\n" % ("ORG_BLUETOOTH_CHARACTERISTIC_MESH_PROVISIONING_DATA_OUT", "0x2ADC", '')) 7636d972adSMilanka Ringwald fout.write("#define %-80s %s // %s\n" % ("ORG_BLUETOOTH_CHARACTERISTIC_MESH_PROXY_DATA_IN" , "0x2ADD", '')) 7736d972adSMilanka Ringwald fout.write("#define %-80s %s // %s\n" % ("ORG_BLUETOOTH_CHARACTERISTIC_MESH_PROXY_DATA_OUT" , "0x2ADE", '')) 7836d972adSMilanka Ringwald fout.write("// END(manualy added, missing on Bluetooth Website\n") 790e0e9559SMatthias Ringwald fout.write(trailer) 800e0e9559SMatthias Ringwald 810e0e9559SMatthias Ringwaldprint('Scraping successful!\n') 82