Using bluepy to send and read serial data I am trying to use bluepy to write and read serial data to/from an HC-08 Bluetooth module. The HC-08 is connected to a device that returns a fixed number of bytes whenever it receives a message over the HC-08.
Below is my code so far. This seems to work—however, I kind of winged this code from examples and an a lot of trial and error. I am not entirely sure what I am doing. Therefore, any comments/feedback for potential improvements would be very welcome. The code is implemented as a class myhc08 that has a write method. This method writes a string to the hc08 and then reads out a set number of bytes.
import struct
import bluepy.btle as btle
from matplotlib import pyplot

class ReadDelegate(btle.DefaultDelegate):
    def __init__(self):
        self.data = b''
        
    def reset(self):
        self.data = b''
    
    def handleNotification(self, cHandle, data):
        self.data = self.data + data
    
    @property
    def data_length(self):
        return len(self.data)

class myHC08:
    def __init__(self):
        self.mac = '34:14:B5:50:34:77'
        self.write_service_id = 4
        self.write_service = None
        self.peripheral = btle.Peripheral(self.mac)
        self.delegate = ReadDelegate()
        self.peripheral.withDelegate(self.delegate)
        
    def connect(self):
        s = self.write_service_id
        services = self.peripheral.getServices()
        self.write_service = self.peripheral.getServiceByUUID(list(services)[s].uuid)
    
    def write(self, message, min_bytes, unpack_string=False):
        print('Writing:', message)
        self.delegate.reset()
        c = self.write_service.getCharacteristics()[0]
        c.write(bytes(message, &quot;utf-8&quot;))
        print('Receiving %i bytes' % min_bytes)
        while self.peripheral.waitForNotifications(1): pass
        while self.delegate.data_length &lt; min_bytes: pass
        received = self.delegate.data
        if unpack_string: received = struct.unpack(unpack_string,received)
        return received
        
    def disconnect(self):
        self.peripheral.disconnect()
    


bt = myHC08()
bt.connect()
r = bt.write('1*', 1250*2, '1250H')
bt.disconnect()

In case this helps, my computer lists the following UUIDs for the HC-08 device:
00001800-0000-1000-8000-00805f9b34fb Generic Access
00001801-0000-1000-8000-00805f9b34fb Generic Attribute
0000180a-0000-1000-8000-00805f9b34fb Device Information
0000ffe0-0000-1000-8000-00805f9b34fb Unknown
0000fff0-0000-1000-8000-00805f9b34fb Unknown
Concatenation
In computer science terms, depending on a lot of things, this:
    self.data = self.data + data

can be worst-case O(n^2). This happens when the Python runtime needs to work reallocating everything in the existing buffer before it's able to add new data. One way around this is to use BytesIO instead.
Casting to a list
Based on the documentation:

getServices() / Returns a list of Service objects

Since it's already a list, there is no need to re-cast to a list here:
    self.write_service = self.peripheral.getServiceByUUID(list(services)[s].uuid)

Disconnection safety
Since myHC08 has a disconnect method, it should be made into a context manager, and used in a with statement; or at the least:
bt.connect()
try:
    r = bt.write('1*', 1250*2, '1250H')
finally:
    bt.disconnect()