This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

pc-ble-driver-py example of writing a characteristic.

I'm using the pc-ble-driver-py: Standard Heart Rate example to read a characteristic just fine.

My issue is i now need to write a to a characteristic.

How would I do that given the example above that reads great but can hypothetically write to the same characteristic read?

Link to HR example:

github.com/.../heart_rate_collector.py

  • I figured it out. It's pretty simple, something like this for a custom service: (unverified after sanitizing)

    self.ourBaseUUID = BLEUUIDBase([0x5e, 0x0a, 0xc3, 0x95, 0x70, 0xb0, 0xab, 0xae,
                                    0xfd, 0x23, 0x6b, 0x79, 0x4a, 0x9b, 0x58, 0xda],
                                   2)  # base UUID type=2 (why?)
    self.ourCharUUID = BLEUUID(0x2001, self.ourBaseUUID)

    byte_array = [1, 2, 3, 4]
    self.adapter.write_req(conn_handle, self.ourCharUUID, byte_array)
  • Hi Chris,

    I am doing something like you but I am facing issue. Can you share your working example script?

    I use a nRF52840 Dongle to connect with my Bluetooth Device by modifying heart_rate_collector.py and it is successful. Now I would like to send some HEX code to the Bluetooth Device with python. The action should be similar with the nRF Connect Desktop at the 1401 below. I am sending the HEX command to the device.

  • Hi Wei Jian,

    My full script includes proprietary information, but the following functions that I added to the HRCollector class might be useful. My service has 32-bit characteristics that I call "addr" and "data". In my firmware, I map what I call "registers" to different addresses, so to read a register, I write the address to "addr" and then "data" notifies with the value. To write a register, I then write the value to "data":

    REG_ADDR = {
        "":                 0x0000,
        "FOO":              0x0000,
        "BAR":              0x0004,
    }
    
    # in class HRCollector:
    # in __init__:
            self.return_q   = Queue.Queue()
            self.return_q_q = Queue.Queue()
    # /in __init__
    
        def on_notification(self, ble_adapter, conn_handle, uuid, data):
            if (not self.return_q_q.empty()):  # We are expecting this data, so put it in the next return q:
                ret_q = self.return_q_q.get()
                ret_q.put(data)
            else:                              # Unexpected data, so just print it:
                print('Connection: {}, {} = {}'.format(conn_handle, uuid, data))
    
        def write_word_characteristic(self, conn_handle, uuid, data):
            byte_array = []
            for byte_num in range (0, 4):
                byte_array.append(data >> (8*byte_num) & 0xFF)
            self.adapter.write_req(conn_handle, uuid, byte_array)
       
        def write_addr(self, conn_handle, data):
            self.return_q_q.put(self.return_q)
            self.write_word_characteristic(conn_handle, self.clovisAddrUUID, data)
            byte_array = self.return_q.get(block=True, timeout=30)
            return_data = 0
            for byte_num in range (0, 4):
                return_data = return_data | (byte_array[byte_num] << (8*byte_num))
            return return_data
    
        def write_data(self, conn_handle, data):
            self.write_word_characteristic(conn_handle, self.clovisDataUUID, data)
    
        def write_addr_and_data(self, conn_handle, addr, data):
            self.write_addr(conn_handle, addr)
            self.write_data(conn_handle, data)
    
        def read_register(self, conn_handle, base, addr_name, print_en=False):
            addr_int = base + REG_ADDR[addr_name]
            data = self.write_addr(conn_handle, addr_int)
            if print_en:
                print ('Read register ' + addr_name + '(' + hex(addr_int) + '): ' + hex(data) + " (" + str(data) + " decimal)")
            return(data)
    
        def write_register(self, conn_handle, base, addr_name, data, print_en=False):
            addr_int = base + REG_ADDR[addr_name]
            if print_en:
                print ('Write register ' + addr_name + '(' + hex(addr_int) + ')=' + hex(data))
            self.write_addr(conn_handle, addr_int)
            self.write_data(conn_handle, data)

    I know this is more than you asked for. To just write a characteristic, write_word_characteristic() is all you need. Or, starting from my original example, you should be able to just assign byte_array with the 6 bytes that you want to write, and pass that to write_req. You can do this in main() after connect_and_discover(). What problem are you having?

    Chris

  • Thanks for your sharing Chris.

    I am totally new in BLE so I am facing issue in creating a script to write characteristics. I will try with your script first. Can you roughly explain how you apply this script on your device? Appreciate!

  • Hi Chris,

    From your example script above.

    self.ourBaseUUID = BLEUUIDBase([0x5e, 0x0a, 0xc3, 0x95, 0x70, 0xb0, 0xab, 0xae,
                                    0xfd, 0x23, 0x6b, 0x79, 0x4a, 0x9b, 0x58, 0xda],
                                   2)  # base UUID type=2 (why?)
    self.ourCharUUID = BLEUUID(0x2001, self.ourBaseUUID)

    Can you explain what is BaseUUID and CharUUID? 

Related