Setting Matter bridge to BLE device

Hello.
Thank you for your support.

I am trying to build a BLE bridge for Matter.
I was able to create the Matter Lock sample and Ble app separately, but I am having trouble figuring out how to connect the Ble app from the Matter Lock sample.

Would it be better to connect Matter and BLE app on two nrf52840dk by connecting them with UART from GPIOs?
Or is it better to build BLE app into Matter sample?

Matter Lock sample:
nrf Connect SDK 2.0.0

BLE smart lock app:
Using ble_app_multirole_lesc_s140_pca10056

Thank you.



Parents
  • Hi,

    Can you clarify the use case? Do you want to be able to control the Matter door lock using both Matter (over Thread or Wi-Fi) and Bluetooth LE? BLE is used for commissioning in our Matter samples, so the samples have support for BLE out of the box. It should be possible to add other BLE services to the samples as well, so if what you want is to be able to have the door lock be a Matter/BLE device, this should be possible.

    If you instead want the door lock to only be a Matter device and want to use a gateway for BLE devices to communicate with the door lock through the gateway, then I would recommend that the gateway is a BLE/Matter device that uses Matter for communication with the door lock, instead of using UART.

    Please also be aware that nRF5 SDK is in maintenance mode, so for new development we strongly recommend using nRF Connect SDK, also for BLE.

    Best regards,

    Marte

  • Hello.
    Thanks for your reply.

    What I want is to be able to have the door lock be a Matter/BLE device.
    Therefore, I would like to add a BLE service to the sample.

    I need a peripheral BLE service which has LESC pairing and UART (NUS?) function. Which BLE sample is appropriate with the nRF Connect SDK?

    Also, should the events for locking and unlocking the BLE service be incorporated into the BoltLockManager function on the Matter sample?

    Thank you.

  • Hi,

    The best start would be to look at the Bluetooth: Peripheral UART sample, which demonstrates how to use the Nordic UART Services (NUS).

    For LESC you need to add CONFIG_BT_SMP=y in prj.conf to enable pairing devices over LE. You also need to add several callbacks depending on whether you want to support display, keyboard, accepting/declining bonding, etc. For example:

    static struct bt_conn_auth_cb conn_auth_callbacks = {
        .passkey_display = auth_passkey_display,
        .passkey_confirm = auth_passkey_confirm,
        .cancel = auth_cancel,
    };

    If you look in the Peripheral UART sample you will see that a lot of these callbacks already exists, and depends on CONFIG_BT_NUS_SECURITY_ENABLED being defined.

    Best regards,

    Marte

Reply
  • Hi,

    The best start would be to look at the Bluetooth: Peripheral UART sample, which demonstrates how to use the Nordic UART Services (NUS).

    For LESC you need to add CONFIG_BT_SMP=y in prj.conf to enable pairing devices over LE. You also need to add several callbacks depending on whether you want to support display, keyboard, accepting/declining bonding, etc. For example:

    static struct bt_conn_auth_cb conn_auth_callbacks = {
        .passkey_display = auth_passkey_display,
        .passkey_confirm = auth_passkey_confirm,
        .cancel = auth_cancel,
    };

    If you look in the Peripheral UART sample you will see that a lot of these callbacks already exists, and depends on CONFIG_BT_NUS_SECURITY_ENABLED being defined.

    Best regards,

    Marte

Children
  • Hi Marte,
    I could set up LESC. Thank you.
    Then I would like to have two more questions.

    1. I'd like to send security request from peripheral, so how could I configure it?
    2. I'd like to put manufacture data(company ID) to adv data.
        Where can I configure it?

  • Hi,

    shin.. said:

    1. I'd like to send security request from peripheral, so how could I configure it?

    You can use bt_conn_set_security(). Send in the connection object and requested security level as parameters. As an example, this is done in the Peripheral HIDS sample:

    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (err) {
    		printk("Failed to connect to %s (%u)\n", addr, err);
    		return;
    	}
    
    	printk("Connected %s\n", addr);
    
    	if (bt_conn_set_security(conn, BT_SECURITY_L2)) {
    		printk("Failed to set security\n");
    	}
    }

    shin.. said:
    2. I'd like to put manufacture data(company ID) to adv data.
        Where can I configure it?

    You can add this to the advertisement data struct:

    static uint8_t mfg_data[] = //put manufacturer data here
    
    static const struct bt_data ad[] = {
    	BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, sizeof(mfg_data)),
    };

    Best regards,

    Marte

  • Hi Marte,
    I could build up BLE app with peripheral_UART sample. Thank you.

    Then I would like to merge BLE app into Matter door lock sample.
    How could I set up?

    Shin

  • Hi Shin,

    I think the best way to implement this is to look at how SMP is implemented and used in the Matter samples. I started implementing this myself, but I have not been able to test it yet. I will try to test it and get back to you tomorrow.

    Best regards,

    Marte

  • Hi,

    I was able to successfully test that it works, so I have added the example to github here: https://github.com/martelmy/NCS_examples/tree/main/matter/light_bulb_ble_uart.

    You can use this as a starting point when developing this yourself. I just wanted to make a simple example to test that it works, so now it only handles receiving one character at a time, but you can expand it to receive strings. Look at the Peripheral UART sample for help with this.

    If you want to test this example, make sure to add overlay-multiprotocol_ble.conf as OVERLAY_CONFIG when building, if not, NUS will not be enabled. I sometimes see that the device shows up without a name when scanning, but you can identify it by looking for the NUS UUID. If you are unable to connect to it, press button 3 and try again.

    I will explain what I did so it might be easier to use this or do something similar yourself.

    bt_nus.cpp and bt_nus.h

    In my implementation I looked at how the SMP service is handled, as I mentioned in my previous reply. So if you look in the src directory you can see that I have created two new files: bt_nus.cpp and bt_nus.h. These are similar to the dfu_over_smp files you can find in nrf/samples/matter/common/src in the SDK. I have modified StartBLEAdvertising() to add the correct data for the scan response packets, and I have added OnNUSReceived() to handle receiving NUS events. If you look at OnNUSReceived() you will see that it is very simple, as it only prints the first character received, so here you can add your own implementation.

    CMakeLists.txt

    As mentioned, I have created an overlay file overlay-multiprotocol_ble.conf with the necessary configurations. When you add this to your build, you will set CONFIG_BT_NUS, which will make it so bt_nus.cpp is added as a target_source in CMakeLists.txt:

    if(CONFIG_BT_NUS)
        target_sources(app PRIVATE src/bt_nus.cpp)
    endif()

    app_config.h

    Here I simply added BLE_NUS_BUTTON for button 3, which I use somewhere else to start advertising NUS.

    #define BLE_NUS_BUTTON DK_BTN3
    #define BLE_NUS_BUTTON_MASK DK_BTN3_MSK

    app_event.h

    The only thing I did in app_event.h was to add StartNUSAdvertising to AppEventType:

    enum class AppEventType : uint8_t {
    	None = 0,
    	Button,
    	ButtonPushed,
    	ButtonReleased,
    	Timer,
    	UpdateLedState,
    	Lighting,
    	IdentifyStart,
    	IdentifyStop,
    	StartSMPAdvertising,
    	StartNUSAdvertising
    };

    app_task.h

    Then in app_task.h I include bt_nus.h and added StartBLENUSHandler() and RequestNUSAdvertisingStart() to AppTask:

    class AppTask {
    public:
    
    ...
    
    private:
    
    ...
    
    	static void FunctionHandler(const AppEvent &event);
    	static void StartBLENUSHandler(const AppEvent &event);
    	static void StartBLEAdvertisementAndLightActionEventHandler(const AppEvent &event);
    
    #ifdef CONFIG_MCUMGR_SMP_BT
    	static void RequestSMPAdvertisingStart(void);
    #endif
    
    #ifdef CONFIG_BT_NUS
    	static void RequestNUSAdvertisingStart(void);
    #endif
    
    ...
    };

    app_task.cpp

    Of the existing files, this is the one where I made the most changes.

    I added so that advertising will start during AppTask init by calling RequestNUSAdvertisingStart()

    #ifdef CONFIG_BT_NUS
    	/* Initialize BLE NUS */
    	GetNUS().Init(RequestNUSAdvertisingStart);
    #endif

    This function is implemented a bit further down:

    #ifdef CONFIG_BT_NUS
    void AppTask::RequestNUSAdvertisingStart(void)
    {
    	AppEvent event;
    	event.Type = AppEventType::StartNUSAdvertising;
    	event.Handler = [](const AppEvent &) { GetNUS().StartBLEAdvertising(); };
    	PostEvent(event);
    }
    #endif

    In the ButtonEventHandler I added a check for BLE_NUS_BUTTON (button 3) that calls StartBLENUSHandler().

    if (BLE_NUS_BUTTON & hasChanged) {
    	button_event.ButtonEvent.PinNo = BLE_NUS_BUTTON;
    	button_event.ButtonEvent.Action =
    		static_castuint8_t>((BLE_NUS_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed :
    									    AppEventType::ButtonReleased);
    	button_event.Handler = StartBLENUSHandler;
    	PostEvent(button_event);
    }

    StartBLENUSHandler was implemented further down, and it will start NUS advertising by calling GetNUS().StartServer().

    void AppTask::StartBLENUSHandler(const AppEvent &event)
    {
    	if (event.ButtonEvent.PinNo != BLE_NUS_BUTTON)
    		return;
    	
     	Instance().mFunction = FunctionEvent::NoneSelected;
    
    #ifdef CONFIG_BT_NUS
    		GetNUS().StartServer();
    #else
    		LOG_INF("NUS is disabled");
    #endif
    }

    I hope this helps you get started!

    Best regards,

    Marte

Related