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

Parents
  • The hearth rate device doesn't contain any characteristics that you can write to. Perhaps you can try to modify the heart_rate_collector.py to connect to a device running the ble_app_uart example instead. You should see that this device has two characteristics. One that you can only enable subscriptions on (notifications, just like you do on the battery service in the heart rate example), and another that you can write to. Please check it out without pc-ble-driver-py (connect to it with your phone using the nRF Connect for iOS/Android app) to see how the example is working.

    Best regards,

    Edvin

  • Hi Edvin,

    Can you send me link to example?

    Is that on Github?

  • 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? 

  • This might help answer your questions:
    https://github.com/bjornspockeli/custom_ble_service_example

    Try putting my original example into your script (except using your custom UUIDs and 6 bytes for your characteristic), post your script here with what problem you are having with it, and I will try to help.

    Did you say that you can successfully write your custom characteristic using nRF Connect? You said you can read heart rate using a script, so you are almost there!

Reply Children
No Data
Related