# Buggy code
async def run(address, loop, debug=False):
    if debug:
        import sys

        loop.set_debug(True)
        l = logging.getLogger("asyncio")
        l.setLevel(logging.DEBUG)
        h = logging.StreamHandler(sys.stdout)
        h.setLevel(logging.DEBUG)
        l.addHandler(h)

    async with BleakClient(address, loop=loop) as client:
        x = await client.is_connected()
        logger.info("Connected: {0}".format(x))

        system_id = await client.read_gatt_char(SYSTEM_ID_UUID)
        print(
            "System ID: {0}".format(
                ":".join(["{:02x}".format(x) for x in system_id[::-1]])
            )
        )

        model_number = await client.read_gatt_char(MODEL_NBR_UUID)
        print("Model Number: {0}".format("".join(map(chr, model_number))))

        manufacturer_name = await client.read_gatt_char(MANUFACTURER_NAME_UUID)
        print("Manufacturer Name: {0}".format("".join(map(chr, manufacturer_name))))

        firmware_revision = await client.read_gatt_char(FIRMWARE_REV_UUID)
        print("Firmware Revision: {0}".format("".join(map(chr, firmware_revision))))

        hardware_revision = await client.read_gatt_char(HARDWARE_REV_UUID)
        print("Hardware Revision: {0}".format("".join(map(chr, hardware_revision))))

        software_revision = await client.read_gatt_char(SOFTWARE_REV_UUID)
        print("Software Revision: {0}".format("".join(map(chr, software_revision))))

        battery_level = await client.read_gatt_char(BATTERY_LEVEL_UUID)
        print("Battery Level: {0}%".format(int(battery_level[0])))

        def keypress_handler(sender, data):
            print("{0}: {1}".format(sender, data))

        write_value = bytearray([0xA0])
        value = await client.read_gatt_char(IO_DATA_CHAR_UUID)
        print("I/O Data Pre-Write Value: {0}".format(value))

        await client.write_gatt_char(IO_DATA_CHAR_UUID, write_value)

        value = await client.read_gatt_char(IO_DATA_CHAR_UUID)
        print("I/O Data Post-Write Value: {0}".format(value))
        assert value == write_value

        await client.start_notify(KEY_PRESS_UUID, keypress_handler)
        await asyncio.sleep(5.0, loop=loop)
        await client.stop_notify(KEY_PRESS_UUID)


# Traceback (bleak.exc.BleakError)
/Users/zaytsev/PycharmProjects/bluetooth/venv/bin/python /Users/zaytsev/PycharmProjects/bluetooth/bleak_demo.py
DEBUG:bleak.backends.corebluetooth.CentralManagerDelegate:Bluetooth powered on
DEBUG:bleak.backends.corebluetooth.CentralManagerDelegate:Discovered device A0E49DB2-B7F1-4A65-AB2E-D75121192329: Unknown @ RSSI: -79
A0E49DB2-B7F1-4A65-AB2E-D75121192329: HUAWEI Band 2-b6e
DEBUG:bleak.backends.corebluetooth.client:Connecting to BLE device @ A0E49DB2-B7F1-4A65-AB2E-D75121192329
DEBUG:bleak.backends.corebluetooth.CentralManagerDelegate:Successfully connected to device uuid A0E49DB2-B7F1-4A65-AB2E-D75121192329
WARNING:bleak.backends.corebluetooth.PeripheralDelegate:PeripheralDelegate is not compliant
DEBUG:bleak.backends.corebluetooth.client:Retrieving services...
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Services discovered
DEBUG:bleak.backends.corebluetooth.client:Retrieving characteristics for service 180F
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Characteristics discovered
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic 2A19
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered 2A19
DEBUG:bleak.backends.corebluetooth.client:Retrieving characteristics for service 180A
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Characteristics discovered
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic 2A29
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered 2A29
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic 2A24
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered 2A24
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic 2A26
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered 2A26
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic 2A28
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered 2A28
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic 2A50
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered 2A50
DEBUG:bleak.backends.corebluetooth.client:Retrieving characteristics for service 180D
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Characteristics discovered
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic 2A37
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered 2A37
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic 2A38
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered 2A38
DEBUG:bleak.backends.corebluetooth.client:Retrieving characteristics for service FE86
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Characteristics discovered
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic FE01
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered FE01
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic FE02
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered FE02
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic FE03
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered FE03
DEBUG:bleak.backends.corebluetooth.client:Retrieving descriptors for characteristic FE04
DEBUG:bleak.backends.corebluetooth.PeripheralDelegate:Descriptor discovered FE04
DEBUG:bleak.backends.corebluetooth.client:Retrieving services...
DEBUG:bleak.backends.corebluetooth.client:Retrieving characteristics for service 180F
DEBUG:bleak.backends.corebluetooth.CentralManagerDelegate:Peripheral Device disconnected!
Traceback (most recent call last):
File "/Users/zaytsev/PycharmProjects/bluetooth/bleak_demo.py", line 25, in <module>
loop.run_until_complete(ble_get_services(address, loop))
File "/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete
return future.result()
File "/Users/zaytsev/PycharmProjects/bluetooth/bleak_demo.py", line 18, in ble_get_services
svcs = await client.get_services()
File "/Users/zaytsev/PycharmProjects/bluetooth/venv/lib/python3.7/site-packages/bleak/backends/corebluetooth/client.py", line 118, in get_services
self.services.add_service(BleakGATTServiceCoreBluetooth(service))
File "/Users/zaytsev/PycharmProjects/bluetooth/venv/lib/python3.7/site-packages/bleak/backends/service.py", line 101, in add_service
"This service is already present in this BleakGATTServiceCollection!"
bleak.exc.BleakError: This service is already present in this BleakGATTServiceCollection!

# Fixed code
async def run(address, loop, debug=False):
    if debug:
        import sys

        # loop.set_debug(True)
        # l = logging.getLogger("asyncio")
        # l.setLevel(logging.DEBUG)
        # h = logging.StreamHandler(sys.stdout)
        # h.setLevel(logging.DEBUG)
        # l.addHandler(h)

    async with BleakClient(address, loop=loop) as client:
        x = await client.is_connected()
        logger.info("Connected: {0}".format(x))

        system_id = await client.read_gatt_char(SYSTEM_ID_UUID)
        print(
            "System ID: {0}".format(
                ":".join(["{:02x}".format(x) for x in system_id[::-1]])
            )
        )

        model_number = await client.read_gatt_char(MODEL_NBR_UUID)
        print("Model Number: {0}".format("".join(map(chr, model_number))))

        device_name = await client.read_gatt_char(DEVICE_NAME_UUID)
        print("Device Name: {0}".format("".join(map(chr, device_name))))

        manufacturer_name = await client.read_gatt_char(MANUFACTURER_NAME_UUID)
        print("Manufacturer Name: {0}".format("".join(map(chr, manufacturer_name))))

        firmware_revision = await client.read_gatt_char(FIRMWARE_REV_UUID)
        print("Firmware Revision: {0}".format("".join(map(chr, firmware_revision))))

        hardware_revision = await client.read_gatt_char(HARDWARE_REV_UUID)
        print("Hardware Revision: {0}".format("".join(map(chr, hardware_revision))))

        software_revision = await client.read_gatt_char(SOFTWARE_REV_UUID)
        print("Software Revision: {0}".format("".join(map(chr, software_revision))))

        battery_level = await client.read_gatt_char(BATTERY_LEVEL_UUID)
        print("Battery Level: {0}%".format(int(battery_level[0])))

        def keypress_handler(sender, data):
            print("{0}: {1}".format(sender, data))

        write_value = bytearray([0xA0])
        value = await client.read_gatt_char(IO_DATA_CHAR_UUID)
        print("I/O Data Pre-Write Value: {0}".format(value))

        await client.write_gatt_char(IO_DATA_CHAR_UUID, write_value)

        value = await client.read_gatt_char(IO_DATA_CHAR_UUID)
        print("I/O Data Post-Write Value: {0}".format(value))
        assert value == write_value

        await client.start_notify(KEY_PRESS_UUID, keypress_handler)
        await asyncio.sleep(5.0, loop=loop)
        await client.stop_notify(KEY_PRESS_UUID)