From b31456261c2451f9120cfbb2a8af690b50727d06 Mon Sep 17 00:00:00 2001 From: x Date: Sat, 17 Oct 2020 06:45:25 -0400 Subject: [PATCH] 1. The case where there is no hci0 in the system but there are other hci devices is handled. 2. Used the new logging system. 3. Reparsed the manufacturer specific data in the GAP. 4. Fixed some bugs. --- README-Chinese.md | 4 +-- README.md | 4 +-- setup.py | 20 +++++++++------ src/bluescan/__init__.py | 6 ++--- src/bluescan/__main__.py | 34 ++++++++++++++----------- src/bluescan/br_scan.py | 52 +++++++++++++++++++++------------------ src/bluescan/gatt_scan.py | 8 +++--- src/bluescan/helper.py | 1 - src/bluescan/le_scan.py | 42 ++++++++++++++++++++++--------- src/bluescan/lmp_scan.py | 21 ++++++++++------ src/bluescan/sdp_scan.py | 11 ++++++--- src/bluescan/ui.py | 25 ++++++++++--------- upload2pypi.sh | 6 +++++ upload_pypi.sh | 6 ----- 14 files changed, 140 insertions(+), 100 deletions(-) create mode 100644 upload2pypi.sh delete mode 100644 upload_pypi.sh diff --git a/README-Chinese.md b/README-Chinese.md index 3eb2aac..8cc2517 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -35,7 +35,7 @@ sudo pip3 install bluescan ```txt $ bluescan -h -bluescan v0.2.2 +bluescan v0.2.3 A powerful Bluetooth scanner. @@ -59,7 +59,7 @@ Arguments: Options: -h, --help Display this help. -v, --version Show the version. - -i HCI device for scan. [default: hci0] + -i HCI device for scan. [default: The first HCI device] -m Scan mode, support BR, LE, LMP, SDP, GATT and vuln. --inquiry-len= Inquiry_Length parameter of HCI_Inquiry command. [default: 8] --timeout= Duration of LE scan. [default: 10] diff --git a/README.md b/README.md index a28c74d..635c36d 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ sudo pip3 install bluescan ```txt $ bluescan -h -bluescan v0.2.2 +bluescan v0.2.3 A powerful Bluetooth scanner. @@ -61,7 +61,7 @@ Arguments: Options: -h, --help Display this help. -v, --version Show the version. - -i HCI device for scan. [default: hci0] + -i HCI device for scan. [default: The first HCI device] -m Scan mode, support BR, LE, LMP, SDP, GATT and vuln. --inquiry-len= Inquiry_Length parameter of HCI_Inquiry command. [default: 8] --timeout= Duration of LE scan. [default: 10] diff --git a/setup.py b/setup.py index 1623c26..7a335d1 100644 --- a/setup.py +++ b/setup.py @@ -2,13 +2,17 @@ import os import shutil +import logging from pathlib import Path from setuptools.command.install import install from distutils.command.clean import clean from setuptools import setup, find_packages +from pyclui import Logger -BLUESCAN_PATH = os.path.abspath(Path(__file__).parent) +logger = Logger(__name__, logging.INFO) + +PROJECT_ROOT = os.path.abspath(Path(__file__).parent) def read(fname): @@ -18,7 +22,7 @@ def read(fname): class MyInstall(install): def run(self): super().run() - print('[INFO] install bluescan_prompt.bash') + logger.info('install bluescan_prompt.bash') shutil.copy( 'src/bluescan/bluescan_prompt.bash', '/etc/bash_completion.d' ) @@ -28,10 +32,10 @@ class MyClean(clean): def run(self): super().run() dirs = [ - os.path.join(BLUESCAN_PATH, 'build'), - os.path.join(BLUESCAN_PATH, 'dist'), - os.path.join(BLUESCAN_PATH, 'src', 'bluescan.egg-info'), - os.path.join(BLUESCAN_PATH, 'src', 'bluescan', '__pycache__') + os.path.join(PROJECT_ROOT, 'build'), + os.path.join(PROJECT_ROOT, 'dist'), + os.path.join(PROJECT_ROOT, 'src', 'bluescan.egg-info'), + os.path.join(PROJECT_ROOT, 'src', 'bluescan', '__pycache__') ] for d in dirs: @@ -41,7 +45,7 @@ def run(self): if __name__ == '__main__': setup( name='bluescan', - version='0.2.2', + version='0.2.3', license = "GPL-3.0", packages=find_packages('src'), # include all packages under src package_dir={'':'src'}, # tell distutils packages are under src @@ -56,7 +60,7 @@ def run(self): #scripts=['src/bluescan/bluescan.py'], install_requires=[ - 'bthci>=0.0.6', 'pyclui>=0.0.2', + 'bthci>=0.0.7', 'pyclui>=0.0.3', 'pybluez>=0.23', 'bluepy>=1.3.0', 'docopt>=0.6.2' ], diff --git a/src/bluescan/__init__.py b/src/bluescan/__init__.py index a7802d1..9d91e3a 100644 --- a/src/bluescan/__init__.py +++ b/src/bluescan/__init__.py @@ -5,7 +5,6 @@ from bthci import HCI - # https://www.bluetooth.com/specifications/assigned-numbers/service-discovery/ # Table 2: Service Class Profile Identifiers # @@ -40,13 +39,14 @@ 'Allowed Usage': items[2] } - +# EIR Data Type, Advertising Data Type (AD Type) and OOB Data Type Definitions COMPLETE_16_BIT_SERVICE_CLS_UUID_LIST = 0x03 COMPLETE_32_BIT_SERVICE_CLS_UUID_LIST = 0x05 COMPLETE_128_BIT_SERVICE_CLS_UUID_LIST = 0x07 COMPLETE_LOCAL_NAME = 0X09 SHORTENED_LOCAL_NAME = 0X08 TX_POWER_LEVEL = 0x0a +MANUFACTURER_SPECIFIC_DATA = 0xff gap_type_name_pairs = { 0x01: 'Flags', @@ -99,4 +99,4 @@ class BlueScanner(): def __init__(self, iface='hci0'): self.iface = iface - self.devid = HCI.hcix2devid(self.iface) + self.devid = HCI.hcistr2devid(self.iface) diff --git a/src/bluescan/__main__.py b/src/bluescan/__main__.py index ea75a41..66e10db 100644 --- a/src/bluescan/__main__.py +++ b/src/bluescan/__main__.py @@ -2,21 +2,18 @@ import os import sys -import time +import logging import traceback import subprocess from pathlib import PosixPath +from bthci import HCI +from pyclui import Logger from bluepy.btle import BTLEException from bluetooth.btcommon import BluetoothError -from bthci import HCI -from pyclui import blue, green, yellow, red, \ - DEBUG, INFO, WARNING, ERROR - from .ui import parse_cmdline from .helper import find_rfkill_devid - from .br_scan import BRScanner from .le_scan import LEScanner from .gatt_scan import GATTScanner @@ -26,13 +23,16 @@ from .lmp_scan import LMPScanner +logger = Logger(__name__, logging.INFO) + + def init(iface='hci0'): hci = HCI(iface) exitcode, output = subprocess.getstatusoutput( 'rfkill unblock %d' % find_rfkill_devid(iface)) if exitcode != 0: - print(ERROR, 'rfkill:', output) + logger.error('rfkill: ' + output) sys.exit(exitcode) # hci.reset() @@ -73,6 +73,11 @@ def init(iface='hci0'): def main(): try: args = parse_cmdline() + logger.debug('args: {}'.format(args)) + + if args['-i'] == 'The first HCI device': + args['-i'] = HCI.get_default_hcistr() # May raise IndexError + init(args['-i']) if args['-m'] == 'br': @@ -93,22 +98,23 @@ def main(): elif args['-m'] == 'vuln': VulnScanner(args['-i']).scan(args['BD_ADDR'], args['--addr-type']) else: - print(ERROR, "invalid scan mode") + logger.error('Invalid scan mode') + except IndexError: + logger.error('There is no available HCI device') except BluetoothError as e: - print(ERROR, e) + logger.error('{}'.format(e)) except RuntimeError as e: - print(ERROR, e) + logger.error('{}'.format(e)) except (BTLEException, ValueError) as e: - # print('__main__') - print(ERROR, e) + logger.error('{}'.format(e)) if 'le on' in str(e): print(' No BLE adapter? or missing sudo ?') except KeyboardInterrupt: - print(INFO, args['-m'].upper() + " scan canceled\n") + logger.info(args['-m'].upper() + " scan canceled\n") # except Exception as e: # #traceback.print_exc() # print(ERROR, e) -if __name__ == "__main__": +if __name__ == '__main__': main() diff --git a/src/bluescan/br_scan.py b/src/bluescan/br_scan.py index 64cd13f..5b43b6c 100644 --- a/src/bluescan/br_scan.py +++ b/src/bluescan/br_scan.py @@ -5,6 +5,7 @@ import subprocess import warnings import struct +import logging from bluetooth import DeviceDiscoverer @@ -19,8 +20,8 @@ EVT_EXTENDED_INQUIRY_RESULT, EVT_INQUIRY_COMPLETE from bthci import HCI -from pyclui import green, blue, yellow, red, \ - DEBUG, INFO, WARNING, ERROR +from pyclui import Logger +from pyclui import green, blue, yellow, red from . import BlueScanner from . import service_cls_profile_ids @@ -31,6 +32,9 @@ SHORTENED_LOCAL_NAME, TX_POWER_LEVEL +logger = Logger(__name__, logging.INFO) + + major_dev_clses = { 0b00000: 'Miscellaneous', 0b00001: 'Computer', @@ -47,8 +51,8 @@ class BRScanner(BlueScanner): def inquiry(self, lap=0x9e8b33, inquiry_len=0x08, num_rsp=0x00): - print(INFO, "BR scanning on " + blue("hci%d"%self.devid) + \ - " with timeout " + blue("%.2f sec\n"%(inquiry_len*1.28))+'\n') + logger.info('BR scanning on ' + blue("hci%d"%self.devid) + \ + ' with timeout ' + blue("%.2f sec\n"%(inquiry_len*1.28))+'\n') self.scanned_dev = [] self.remote_name_req_flag = True @@ -72,23 +76,23 @@ def inquiry(self, lap=0x9e8b33, inquiry_len=0x08, num_rsp=0x00): if len(data) >= 4: event_code = data[1] if event_code == EVT_CMD_STATUS: - # print(DEBUG, 'HCI_Command_Status') + logger.debug('HCI_Command_Status') pass elif event_code == EVT_INQUIRY_RESULT: - print(DEBUG, 'HCI_Inquiry_Result') + logger.debug('HCI_Inquiry_Result') self.pp_inquiry_result(data[3:]) elif event_code == EVT_INQUIRY_RESULT_WITH_RSSI: - # print(DEBUG, 'HCI_Inquiry_Result_with_RSSI') + logger.debug('HCI_Inquiry_Result_with_RSSI') self.pp_inquiry_result_with_rssi(data[3:]) elif event_code == EVT_EXTENDED_INQUIRY_RESULT: - # print(DEBUG, 'HCI_Extended_Inquiry_Result') + logger.debug('HCI_Extended_Inquiry_Result') self.pp_extended_inquiry_result(data[3:]) elif event_code == EVT_INQUIRY_COMPLETE: - # print(DEBUG, 'HCI_Inquiry_Complete') - print(INFO, 'Inquiry completed\n') + logger.debug('HCI_Inquiry_Complete') + logger.info('Inquiry completed\n') - if self.remote_name_req_flag: - print(INFO, 'Requesting the name of the scanned devices...') + if self.remote_name_req_flag and len(self.scanned_dev) != 0: + logger.info('Requesting the name of the scanned devices...') for bd_addr in self.scanned_dev: try: name = HCI(self.iface).remote_name_request({ @@ -103,9 +107,9 @@ def inquiry(self, lap=0x9e8b33, inquiry_len=0x08, num_rsp=0x00): print(bd_addr+':', blue(name)) break else: - print(DEBUG, "Unknow:", data) + logger.debug('Unknow: {}'.format(data)) except KeyboardInterrupt as e: - print(INFO, "BR/EDR devices scan canceled\n") + logger.info('BR/EDR devices scan canceled\n') HCI(self.iface).inquiry_cancel() hci_close_dev(dd.fileno()) @@ -115,8 +119,8 @@ def pp_inquiry_result(self, params): '''Parse and print HCI_Inquiry_Result.''' num_rsp = params[0] if num_rsp != 1: - print(INFO, 'Num_Responses in HCI_Inquiry_Result is %d.'%num_rsp) - print(DEBUG, 'HCI_Inquiry_Result:', params) + logger.info('Num_Responses in HCI_Inquiry_Result is %d.'%num_rsp) + logger.debug('HCI_Inquiry_Result: {}'.format(params)) return bd_addr, page_scan_repetition_mode, reserved, cod, clk_offset = \ @@ -147,8 +151,8 @@ def pp_inquiry_result_with_rssi(self, params): '''Parse and print HCI_Inquiry_Result_with_RSSI.''' num_rsp = params[0] if num_rsp != 1: - print(INFO, 'Num_Responses in HCI_Inquiry_Result_with_RSSI is %d.'%num_rsp) - print(DEBUG, 'HCI_Inquiry_Result_with_RSSI:', params) + logger.info('Num_Responses in HCI_Inquiry_Result_with_RSSI is %d.'%num_rsp) + logger.debug('HCI_Inquiry_Result_with_RSSI: {}'.format(params)) return bd_addr, page_scan_repetition_mode, reserved, cod, clk_offset, rssi = \ @@ -179,8 +183,8 @@ def pp_extended_inquiry_result(self, params): '''Parse and print HCI_Extended_Inquiry_Result''' num_rsp = params[0] if num_rsp != 1: - print(INFO, 'Num_Responses in HCI_Extended_Inquiry_Result is %d.'%num_rsp) - print(DEBUG, 'HCI_Extended_Inquiry_Result:', params) + logger.info('Num_Responses in HCI_Extended_Inquiry_Result is %d.'%num_rsp) + logger.debug('HCI_Extended_Inquiry_Result: {}'.format(params)) return bd_addr, page_scan_repetition_mode, reserved, cod, \ @@ -223,9 +227,9 @@ def pp_page_scan_repetition_mode(val): def pp_cod(cod:int): '''Print and parse the Class of Device.''' - #print(DEBUG, 'br_scan.py pp_cod()') + logger.debug('Entered br_scan.py, pp_cod()') if cod > 0xFFFFFF or cod & 0x000003 != 0: - print(WARNING, "CoD's Format Type is not format #1") + logger.warning('CoD\'s Format Type is not format #1') return print('\tService Class: %s' % bin(cod>>13)) @@ -315,7 +319,7 @@ def pp_ext_inquiry_rsp(ext_inq_rsp): if length - 1 >= 4: eir_data = data[1:] if len(eir_data) % 4 != 0: - print('\t\t'+INFO, 'Invalid EIR data length: %d'%len(eir_data), eir_data) + logger.info('\t\tInvalid EIR data length: {} {}'.format(len(eir_data), eir_data)) continue for i in range(0, len(eir_data), 4): uuid = int.from_bytes(eir_data[i:i+4], byteorder='little') @@ -327,7 +331,7 @@ def pp_ext_inquiry_rsp(ext_inq_rsp): if length - 1 >= 16: eir_data = data[1:] if len(eir_data) % 16 != 0: - print('\t\t'+INFO, 'Invalid EIR data length: %d'%len(eir_data), eir_data) + logger.info('\t\tInvalid EIR data length: {} {}'.format(len(eir_data), eir_data)) continue for i in range(0, len(eir_data), 16): uuid = int.from_bytes(eir_data[i:i+16], byteorder='little') diff --git a/src/bluescan/gatt_scan.py b/src/bluescan/gatt_scan.py index 4b34156..cc8148e 100644 --- a/src/bluescan/gatt_scan.py +++ b/src/bluescan/gatt_scan.py @@ -3,15 +3,13 @@ import sys import io +import pkg_resources from bluepy.btle import Peripheral from bluepy.btle import BTLEException +from pyclui import green, blue, yellow, red from . import BlueScanner -import pkg_resources - -from pyclui import green, blue, yellow, red, \ - DEBUG, INFO, WARNING, ERROR # char_uuid = pkg_resources.resource_string() # service_uuid = pkg_resources.resource_string() @@ -96,7 +94,7 @@ def scan(self, bdaddr, addr_type, include_descriptor:bool): print(yellow('\tCharacteristic'), '(%s descriptors)' % len(descriptors)) #print('-'*8) print('\t\tHandle: %#06x' % (characteristic.getHandle() - 1)) - print('\t\tType: 0x2803 (tCharacteristic)') + print('\t\tType: 0x2803 (Characteristic)') print('\t\tValue:') print('\t\t\tCharacteristic properties:', green(characteristic.propertiesToString())) print('\t\t\tCharacteristic value handle: %#06x' % characteristic.getHandle()) diff --git a/src/bluescan/helper.py b/src/bluescan/helper.py index 6034b24..fdb8754 100644 --- a/src/bluescan/helper.py +++ b/src/bluescan/helper.py @@ -5,7 +5,6 @@ import subprocess from pyclui import blue, green, yellow, red -from pyclui import DEBUG, ERROR, INFO, ERROR def valid_bdaddr(addr:str) -> bool: diff --git a/src/bluescan/le_scan.py b/src/bluescan/le_scan.py index 36d35d1..34c230c 100644 --- a/src/bluescan/le_scan.py +++ b/src/bluescan/le_scan.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import re +import logging + from bluepy.btle import Scanner from bluepy.btle import DefaultDelegate - -from pyclui import blue, green, yellow, red, \ - DEBUG, INFO, WARNING, ERROR - -import re +from pyclui import Logger +from pyclui import blue, green, yellow, red from . import BlueScanner from . import service_cls_profile_ids @@ -14,7 +14,10 @@ COMPLETE_16_BIT_SERVICE_CLS_UUID_LIST, \ COMPLETE_32_BIT_SERVICE_CLS_UUID_LIST, \ COMPLETE_128_BIT_SERVICE_CLS_UUID_LIST, COMPLETE_LOCAL_NAME, \ - SHORTENED_LOCAL_NAME, TX_POWER_LEVEL + SHORTENED_LOCAL_NAME, TX_POWER_LEVEL, MANUFACTURER_SPECIFIC_DATA + + +logger = Logger(__name__, logging.INFO) # 这个字典暂时没用,以后可能用来判断收到的 advertising 类型 @@ -52,14 +55,16 @@ def scan(self, timeout=8, scan_type='active', sort='rssi'): # scan() 返回的 devs 是 dictionary view。 if scan_type == 'active': # Active scan 会在 LL 发送 SCAN_REQ PDU - print(WARNING, 'Before doing an active scan, make sure you spoof your BD_ADDR.') - print(INFO, "LE active scanning on \x1B[1;34mhci%d\x1B[0m with timeout %d sec\n" % (self.devid, timeout)) + logger.warning('Before doing an active scan, make sure you spoof your BD_ADDR.') + logger.info('LE active scanning on %s with timeout %d sec\n' % \ + (blue('hci%d'%self.devid), timeout)) devs = scanner.scan(timeout) elif scan_type == 'passive': - print("LE passive scanning on \x1B[1;34mhci%d\x1B[0m with timeout %d sec\n" % (self.deivd, timeout)) + logger.info('LE passive scanning on %s with timeout %d sec\n' % \ + (blue('hci%d'%self.devid), timeout)) devs = scanner.scan(timeout, passive=True) else: - print(ERROR, "Unknown LE scan type.") + logger.error('Unknown LE scan type') return if sort == 'rssi': @@ -96,9 +101,22 @@ def scan(self, timeout=8, scan_type='active', sort='rssi'): # adtype 表示当前一条 GAP 数据(AD structure)的类型。 print('\t'+desc+': ', end='') if adtype == COMPLETE_16_BIT_SERVICE_CLS_UUID_LIST: - print() for uuid in val.split(','): - print('\t\t'+blue(uuid)) + print() + if len(uuid) == 36: + # 这里拿到的是完整的 128-bit uuid,但我们需要 16-bit uuid。 + print('\t\t'+blue(uuid[4:8])) + else: + print('\t\t'+blue(uuid)) + continue + elif adtype == MANUFACTURER_SPECIFIC_DATA: + val = bytes.fromhex(val) + if len(val) > 2: + print() + print('\t\tCompany ID:', '0x%04x'%int.from_bytes(val[0:2], 'little', signed=False)) + print('\t\tData:', val[2:]) + else: + print(val) continue print(val) print("\n") diff --git a/src/bluescan/lmp_scan.py b/src/bluescan/lmp_scan.py index 281be6c..ca53b56 100644 --- a/src/bluescan/lmp_scan.py +++ b/src/bluescan/lmp_scan.py @@ -1,14 +1,19 @@ #!/usr/bin/env python3 -from pyclui import blue, green, blue, red, \ - DEBUG, INFO, WARNING, ERROR +import sys +import logging +from pyclui import Logger +from pyclui import blue, green, blue, red from bthci import HCI from . import BlueScanner from .ll import ll_vers +logger = Logger(__name__, logging.INFO) + + lm_vers = { 0: 'Bluetooth Core Specification 1.0b (Withdrawn)', 1: 'Bluetooth Core Specification 1.1 (Withdrawn)', @@ -38,7 +43,7 @@ def scan(self, remote_bd_addr:str): }) if event_params['Status'] != 0: - print(ERROR, 'Failed to create ACL connection') + logger.error('Failed to create ACL connection') sys.exit(1) event_params = hci.read_remote_version_information(cmd_params={ @@ -46,7 +51,7 @@ def scan(self, remote_bd_addr:str): }) if event_params['Status'] != 0: - print(ERROR, 'Failed to read remote version') + logger.error('Failed to read remote version') sys.exit(1) print(blue('Version')) @@ -60,7 +65,7 @@ def scan(self, remote_bd_addr:str): 'Connection_Handle': event_params['Connection_Handle'] }) if event_params['Status'] != 0: - print(ERROR, 'Failed to read remote supported features') + logger.error('Failed to read remote supported features') else: print(blue('LMP features')) pp_lmp_features(event_params['LMP_Features']) @@ -75,7 +80,7 @@ def scan(self, remote_bd_addr:str): 'Page_Number': 0x00 }) if event_params['Status'] != 0: - print(ERROR, 'Failed to read remote extented features') + logger.error('Failed to read remote extented features') else: pp_ext_lmp_features(event_params['Extended_LMP_Features'], 0) for i in range(1, event_params['Maximum_Page_Number']+1): @@ -83,7 +88,7 @@ def scan(self, remote_bd_addr:str): 'Connection_Handle': event_params['Connection_Handle'], 'Page_Number': i}) if event_params['Status'] != 0: - print(ERROR, 'Failed to read remote extented features, page', i) + logger.error('Failed to read remote extented features, page {}'.format(i)) else: pp_ext_lmp_features(event_params['Extended_LMP_Features'], i) @@ -203,4 +208,4 @@ def pp_ext_lmp_features(ext_lmp_features:bytes, page_num:int): print(' Slot Availability Mask:', green('True') if (b >> 2) & 0x01 else red('False')) print(' Train nudging:', green('True') if (b >> 3) & 0x01 else red('False')) else: - print(WARNING, 'Unknown page number', page_num) + logger.warning('Unknown page number {}'.format(page_num)) diff --git a/src/bluescan/sdp_scan.py b/src/bluescan/sdp_scan.py index addf0ba..ad5e341 100644 --- a/src/bluescan/sdp_scan.py +++ b/src/bluescan/sdp_scan.py @@ -2,19 +2,24 @@ import re import sys +import logging import subprocess from bluetooth import find_service from xml.etree import ElementTree from . import BlueScanner from .service_record import ServiceRecord -from pyclui import green, blue, yellow, red, \ - DEBUG, INFO, WARNING, ERROR + +from pyclui import Logger +from pyclui import green, blue, yellow, red + + +logger = Logger(__name__, logging.INFO) class SDPScanner(BlueScanner): def scan(self, addr:str): - print(INFO, 'Scanning...') + logger.info('Scanning...') exitcode, output = subprocess.getstatusoutput('sdptool records --xml ' + addr) if exitcode != 0: sys.exit(exitcode) diff --git a/src/bluescan/ui.py b/src/bluescan/ui.py index d7087ba..c276c55 100644 --- a/src/bluescan/ui.py +++ b/src/bluescan/ui.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -r'''bluescan v0.2.2 +r'''bluescan v0.2.3 A powerful Bluetooth scanner. @@ -24,7 +24,7 @@ Options: -h, --help Display this help. -v, --version Show the version. - -i HCI device for scan. [default: hci0] + -i HCI device for scan. [default: The first HCI device] -m Scan mode, support BR, LE, LMP, SDP, GATT and vuln. --inquiry-len= Inquiry_Length parameter of HCI_Inquiry command. [default: 8] --timeout= Duration of LE scan. [default: 10] @@ -34,13 +34,18 @@ --addr-type= Public, random or BR. ''' -from pyclui import green, blue, yellow, red, \ - DEBUG, INFO, WARNING, ERROR + +import logging + +from pyclui import Logger from docopt import docopt from .helper import valid_bdaddr +logger = Logger(__name__, logging.INFO) + + def parse_cmdline() -> dict: args = docopt(__doc__, version='v0.2.2', options_first=True) #print("[Debug] args =", args) @@ -54,22 +59,18 @@ def parse_cmdline() -> dict: try: if args['-m'] == 'gatt' or args['-m'] == 'sdp': if args['BD_ADDR'] is None: - raise ValueError(ERROR + 'Need BD_ADDR') + raise ValueError('Need BD_ADDR') else: args['BD_ADDR'] = args['BD_ADDR'].lower() if not valid_bdaddr(args['BD_ADDR']): - raise ValueError( - ERROR + ' ' + 'Invalid BD_ADDR: ' + args['BD_ADDR'] - ) + raise ValueError('Invalid BD_ADDR: ' + args['BD_ADDR']) if args['-m'] == 'gatt': if args['--addr-type'] not in ('public', 'random'): - raise ValueError( - ERROR + ' ' + 'Invalid address type, must be public or random' - ) + raise ValueError('Invalid address type, must be public or random') args['--addr-type'] = args['--addr-type'].lower() except ValueError as e: - print(e) + logger.error('{}'.format(e)) exit(1) return args diff --git a/upload2pypi.sh b/upload2pypi.sh new file mode 100644 index 0000000..b7b8481 --- /dev/null +++ b/upload2pypi.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +sudo ./setup.py clean +sudo ./setup.py check +sudo ./setup.py sdist bdist_wheel +twine upload dist/* diff --git a/upload_pypi.sh b/upload_pypi.sh deleted file mode 100644 index 94ae2dd..0000000 --- a/upload_pypi.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -./setup.py clean -./setup.py check -./setup.py sdist bdist_wheel -twine upload dist/*