Skip to content

Commit e36876e

Browse files
Adam-MaciugaArekBalysNordic
authored andcommitted
Applications: matter bridge: code refactor
Unified code to a common place Extended docs secion on adding new protocol Signed-off-by: Adam Maciuga <[email protected]>
1 parent 36da457 commit e36876e

27 files changed

+101
-52
lines changed

applications/matter_bridge/CMakeLists.txt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,36 @@ target_include_directories(app PRIVATE
2828
src
2929
src/bridged_device_types
3030
${ZAP_PARENT_DIR}
31-
${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/
32-
${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/util
31+
src/core/util
32+
src/core
3333
)
3434

3535
target_sources(app PRIVATE
3636
src/app_task.cpp
3737
src/main.cpp
3838
src/bridge_shell.cpp
3939
src/zcl_callbacks.cpp
40-
${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/bridge_manager.cpp
41-
${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/matter_bridged_device.cpp
42-
${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/bridge_storage_manager.cpp
43-
${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/bridged_device_data_provider.cpp
40+
src/core/bridge_manager.cpp
41+
src/core/matter_bridged_device.cpp
42+
src/core/bridge_storage_manager.cpp
43+
src/core/bridged_device_data_provider.cpp
4444
${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/binding/binding_handler.cpp
4545
)
4646

4747
if(CONFIG_BRIDGED_DEVICE_BT)
4848
target_sources(app PRIVATE
49-
${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/ble_connectivity_manager.cpp
50-
src/ble_providers/ble_bridged_device_factory.cpp
49+
src/ble/ble_connectivity_manager.cpp
50+
src/ble/ble_bridged_device_factory.cpp
51+
)
52+
target_include_directories(app PRIVATE
53+
src/ble
54+
src/ble/data_providers
5155
)
52-
target_include_directories(app PRIVATE src/ble_providers)
5356

5457
if(CONFIG_BRIDGE_ONOFF_LIGHT_BRIDGED_DEVICE AND (CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE OR CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE))
5558
target_sources(app PRIVATE
5659
src/bridged_device_types/onoff_light.cpp
57-
src/ble_providers/ble_lbs_data_provider.cpp
60+
src/ble/data_providers/ble_lbs_data_provider.cpp
5861
)
5962

6063
if(CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE)
@@ -84,7 +87,7 @@ endif() # CONFIG_BRIDGE_TEMPERATURE_SENSOR_BRIDGED_DEVICE
8487
# Assume it makes no sense to support BLE environmental sensor without all Matter counterparts
8588
if(CONFIG_BRIDGE_TEMPERATURE_SENSOR_BRIDGED_DEVICE AND CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE)
8689
target_sources(app PRIVATE
87-
src/ble_providers/ble_environmental_data_provider.cpp
90+
src/ble/data_providers/ble_environmental_data_provider.cpp
8891
)
8992
endif() # CONFIG_BRIDGE_TEMPERATURE_SENSOR_BRIDGED_DEVICE AND CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE
9093

applications/matter_bridge/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,6 @@ config BRIDGE_EXPERIMENTAL
186186

187187
source "$(ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR)/config/nrfconnect/chip-module/Kconfig.features"
188188
source "$(ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR)/config/nrfconnect/chip-module/Kconfig.defaults"
189-
source "$(ZEPHYR_NRF_MODULE_DIR)/samples/matter/common/src/bridge/Kconfig"
189+
source "$(ZEPHYR_NRF_MODULE_DIR)/applications/matter_bridge/src/core/Kconfig"
190190
source "$(ZEPHYR_NRF_MODULE_DIR)/samples/matter/common/src/Kconfig"
191191
source "Kconfig.zephyr"

applications/matter_bridge/doc/adding_ble_bridged_device_service.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ The following steps show how to add support for a new Bluetooth LE service calle
3131

3232
#. Implement the ``Bridged Device Data Provider`` role.
3333

34-
a. Create the :file:`my_bt_service_data_provider.cpp` and :file:`my_bt_service_data_provider.h` files for your Bluetooth LE Data Provider in the :file:`src/ble_providers` directory.
35-
#. Open the :file:`nrf/samples/matter/common/src/bridge/ble_bridged_device.h` header file and find the :c:struct:`BLEBridgedDeviceProvider` class constructor.
34+
a. Create the :file:`my_bt_service_data_provider.cpp` and :file:`my_bt_service_data_provider.h` files for your Bluetooth LE Data Provider in the :file:`src/ble/data_providers` directory.
35+
#. Open the :file:`nrf/applications/matter_bridge/src/ble/data_providers/ble_bridged_device.h` header file and find the :c:struct:`BLEBridgedDeviceProvider` class constructor.
3636
Note the constructor signature, it will be used in the child class implemented in the next steps.
3737
#. Add a new :c:struct:`MyBtServiceDataProvider` class inheriting :c:struct:`BLEBridgedDeviceProvider`, and implement its constructor in the :file:`my_bt_service_data_provider.h` file.
3838

@@ -50,7 +50,7 @@ The following steps show how to add support for a new Bluetooth LE service calle
5050

5151
};
5252

53-
#. Open the :file:`nrf/samples/matter/common/src/bridge/ble_bridged_device.h` header file again to see which methods of :c:struct:`BLEBridgedDeviceProvider` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`MyBtServiceDataProvider` class.
53+
#. Open the :file:`nrf/applications/matter_bridge/src/ble/data_providers/ble_bridged_device.h` header file again to see which methods of :c:struct:`BLEBridgedDeviceProvider` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`MyBtServiceDataProvider` class.
5454

5555
Note that :c:struct:`BLEBridgedDeviceProvider` inherits from the :c:struct:`BridgedDeviceDataProvider` class, so the :c:struct:`MyBtServiceDataProvider` class has to implement the purely virtual methods of :c:struct:`BridgedDeviceDataProvider` as well.
5656
#. Edit the :c:struct:`MyBtServiceDataProvider` class in the :file:`my_bt_service_data_provider.h` header file to declare the required methods as follows:
@@ -247,12 +247,12 @@ The following steps show how to add support for a new Bluetooth LE service calle
247247
.. code-block:: cmake
248248
249249
target_sources(app PRIVATE
250-
src/ble_providers/my_bt_service_data_provider.cpp
250+
src/ble/data_providers/my_bt_service_data_provider.cpp
251251
)
252252
253253
#. Provide an allocator for ``MyBtServiceDataProvider`` object creation.
254254
The Matter Bridge application uses a :c:struct:`BleBridgedDeviceFactory` factory module that creates paired ``Matter Bridged Device`` and ``Bridged Device Data Provider`` objects matching a specific Matter device type ID.
255-
To add support for creating the ``MyBtServiceDataProvider`` object, edit the :file:`src/ble_providers/ble_bridged_device_factory.h` and :file:`src/ble_providers/ble_bridged_device_factory.cpp` files as follows:
255+
To add support for creating the ``MyBtServiceDataProvider`` object, edit the :file:`src/ble/ble_bridged_device_factory.h` and :file:`src/ble/ble_bridged_device_factory.cpp` files as follows:
256256

257257
- :file:`ble_bridged_device_factory.h`
258258

@@ -270,7 +270,7 @@ The following steps show how to add support for a new Bluetooth LE service calle
270270

271271
#. Provide mapping between the ``My Bt Service`` UUID and corresponding Matter device types in the helper methods.
272272

273-
a. Add the ``MyBtService`` UUID in the :c:enum:`ServiceUuid` declaration, in the :file:`src/ble_providers/ble_bridged_device_factory.h` header file.
274-
#. Perform proper mapping of Bluetooth UUID and Matter device types in the :c:func:`MatterDeviceTypeToBleService` and :c:func:`BleServiceToMatterDeviceType` methods, in the :file:`src/ble_providers/ble_bridged_device_factory.cpp` file.
273+
a. Add the ``MyBtService`` UUID in the :c:enum:`ServiceUuid` declaration, in the :file:`src/ble/ble_bridged_device_factory.h` header file.
274+
#. Perform proper mapping of Bluetooth UUID and Matter device types in the :c:func:`MatterDeviceTypeToBleService` and :c:func:`BleServiceToMatterDeviceType` methods, in the :file:`src/ble/ble_bridged_device_factory.cpp` file.
275275

276276
#. Compile the target and test it following the steps from the :ref:`Matter Bridge application testing <matter_bridge_testing>` section.

applications/matter_bridge/doc/adding_bridged_matter_device.rst

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ The following steps show how to add support for a new Matter device type, using
1818
#. Implement the ``Matter Bridged Device`` role.
1919

2020
a. Create the :file:`pressure_sensor.cpp` and :file:`pressure_sensor.h` files in the :file:`src/bridged_device_types` directory.
21-
#. Open the :file:`nrf/samples/matter/common/src/bridge/matter_bridged_device.h` header file and find the :c:struct:`MatterBridgedDevice` class constructor.
21+
#. Open the :file:`nrf/applications/matter_bridge/src/core/matter_bridged_device.h` header file and find the :c:struct:`MatterBridgedDevice` class constructor.
2222
Note the constructor signature, it will be used in the child class implemented in the next steps.
2323
#. Add a new :c:struct:`PressureSensorDevice` class inheriting :c:struct:`MatterBridgedDevice`, and implement its constructor in the :file:`pressure_sensor.cpp` and :file:`pressure_sensor.h` files.
2424

@@ -49,7 +49,7 @@ The following steps show how to add support for a new Matter device type, using
4949
5050
#. Declare all clusters that are mandatory for the Pressure Sensor device type, according to the Matter device library specification, and fill the appropriate :c:struct:`MatterBridgedDevice` class fields in the :c:struct:`PressureSensorDevice` class constructor.
5151

52-
The Pressure Sensor device requires the ``Descriptor``, ``Bridged Device Basic Information`` and ``Identify`` clusters, which can be declared using helper macros from the :file:`nrf/samples/matter/common/src/bridge/matter_bridged_device.h` header file, and the ``Pressure Measurement`` cluster, which has to be defined in the application.
52+
The Pressure Sensor device requires the ``Descriptor``, ``Bridged Device Basic Information`` and ``Identify`` clusters, which can be declared using helper macros from the :file:`nrf/applications/matter_bridge/src/core/matter_bridged_device.h` header file, and the ``Pressure Measurement`` cluster, which has to be defined in the application.
5353
Edit the :file:`pressure_sensor.cpp` file as follows:
5454

5555
- Add:
@@ -109,7 +109,7 @@ The following steps show how to add support for a new Matter device type, using
109109
mDataVersion = static_cast<DataVersion *>(chip::Platform::MemoryAlloc(sizeof(DataVersion) * mDataVersionSize));
110110
}
111111
112-
#. Open the :file:`nrf/samples/matter/common/src/bridge/matter_bridged_device.h` header file again to see which methods of the :c:struct:`MatterBridgedDevice` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`PressureSensorDevice` class.
112+
#. Open the :file:`nrf/applications/matter_bridge/src/core/matter_bridged_device.h` header file again to see which methods of the :c:struct:`MatterBridgedDevice` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`PressureSensorDevice` class.
113113
#. Edit the :c:struct:`PressureSensorDevice` class in the :file:`pressure_sensor.h` header file to declare the required methods as follows:
114114

115115
.. code-block:: C++
@@ -118,7 +118,8 @@ The following steps show how to add support for a new Matter device type, using
118118

119119
CHIP_ERROR HandleRead(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer,
120120
uint16_t maxReadLength) override;
121-
CHIP_ERROR HandleWrite(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) override;
121+
CHIP_ERROR HandleWrite(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer,
122+
size_t size) override
122123
CHIP_ERROR HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data,
123124
size_t dataSize) override;
124125
@@ -257,7 +258,7 @@ The following steps show how to add support for a new Matter device type, using
257258
#. Implement the ``Bridged Device Data Provider`` role.
258259

259260
a. Create the :file:`simulated_pressure_sensor_data_provider.cpp` and :file:`simulated_pressure_sensor_data_provider.h` files in the :file:`src/simulated_providers` directory.
260-
#. Open the :file:`nrf/samples/matter/common/src/bridge/bridged_device_data_provider.h` header file and find the :c:struct:`BridgedDeviceDataProvider` class constructor.
261+
#. Open the :file:`nrf/applications/matter_bridge/src/core/bridged_device_data_provider.h` header file and find the :c:struct:`BridgedDeviceDataProvider` class constructor.
261262
Note the constructor signature, it will be used in the child class implemented in the next steps.
262263
#. Add a new :c:struct:`SimulatedPressureSensorDataProvider` class inheriting :c:struct:`BridgedDeviceDataProvider`, and implement its constructor in the :file:`simulated_pressure_sensor_data_provider.h` header file.
263264

@@ -275,7 +276,7 @@ The following steps show how to add support for a new Matter device type, using
275276
~SimulatedPressureSensorDataProvider() {}
276277
};
277278

278-
#. Open the :file:`nrf/samples/matter/common/src/bridge/bridged_device_data_provider.h` header file again to see which methods of the :c:struct:`BridgedDeviceDataProvider` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`SimulatedPressureSensorDataProvider` class.
279+
#. Open the :file:`nrf/applications/matter_bridge/src/core/bridged_device_data_provider.h` header file again to see which methods of the :c:struct:`BridgedDeviceDataProvider` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`SimulatedPressureSensorDataProvider` class.
279280
#. Edit the :c:struct:`SimulatedPressureSensorDataProvider` class in the :file:`simulated_pressure_sensor_data_provider.h` header file to declare the required methods as follows:
280281

281282
.. code-block:: C++
@@ -396,7 +397,7 @@ The following steps show how to add support for a new Matter device type, using
396397
.. code-block:: C++
397398

398399
{ PressureSensorDevice::kPressureSensorDeviceTypeId,
399-
[checkUniqueID, checkLabel](const char *nodeLabel) -> Nrf::MatterBridgedDevice * {
400+
[checkUniqueID, checkLabel](const char* uniqueID, const char* nodeLabel) -> Nrf::MatterBridgedDevice * {
400401
if (!checkUniqueID(uniqueID) || !checkLabel(nodeLabel)) {
401402
return nullptr;
402403
}
@@ -412,4 +413,4 @@ The following steps show how to add support for a new Matter device type, using
412413
return chip::Platform::New<SimulatedPressureSensorDataProvider>(updateClb, commandClb);
413414
} },
414415

415-
5. Compile the target and test it following the steps from the :ref:`Matter Bridge application testing <matter_bridge_testing>` section.
416+
#. Compile the target and test it following the steps from the :ref:`Matter Bridge application testing <matter_bridge_testing>` section.

applications/matter_bridge/doc/adding_bridged_protocol.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,43 @@ This allows updating the Matter Data Model state and also enables handling Matte
1818
The subscription handling can be implemented either by utilizing the implemented protocol's native support for pushing notifications by the end device, or by performing periodic data polling, which is less efficient.
1919

2020
If the Matter device can perform write operations or be controlled using Matter invoke command operations, the ``Bridged Device Data Provider`` shall be able to send appropriate information to the physical end device.
21+
22+
Complete the following steps to add support for a proprietary protocol:
23+
24+
1. Create a ``MyProtocol Data Provider`` class that inherits from the ``Bridged Device Data Provider`` class.
25+
This class should contain all the data and logic used by all your bridged devices.
26+
For reference, see the implementation in the :file:`src/ble/data_providers/ble_bridged_device.h` file.
27+
28+
#. For each bridged device type, create a ``MyProtocol MyDevice Data Provider`` class that inherits from the ``MyProtocol Data Provider`` class.
29+
These classes keep the state of the Matter device synchronized with the state of the device, using the following functions:
30+
* :c:func:`NotifyUpdateState` - Called to notify the bridge when the bridged device changed state.
31+
* :c:func:`UpdateState` - Called by the bridge when the bridged device should update its state (for example, turning a light on or off).
32+
33+
#. Create a ``MyProtocol Connectivity Manager`` class that holds information about all current connections of the bridged device.
34+
This class must implement the following functions:
35+
36+
.. code-block:: C++
37+
38+
CHIP_ERROR AddMyProtocolProvider(MyProtocolBridgedDeviceProvider *provider, const MyProtocolId &deviceId);
39+
CHIP_ERROR RemoveMyProtocolProvider(const MyProtocolId &deviceId);
40+
MyProtocolBridgedDeviceProvider *FindMyProtocolProvider(const MyProtocolId &deviceId);
41+
42+
This class takes care of any connection-related code that your protocol needs.
43+
44+
#. Create a ``MyProtocol Bridged Device Factory`` class that handles device creation, storage, and removal.
45+
46+
#. Adapt the main application to use your newly created classes.
47+
Create a new ``BRIDGED_DEVICE_MY_PROTOCOL`` configuration, go through the application code and find where the :ref:`CONFIG_BRIDGED_DEVICE_BT <CONFIG_BRIDGED_DEVICE_BT>` Kconfig option is used by the preprocessor.
48+
Add support for your protocol in the found instances.
49+
50+
An application with support for ``MyProtocol`` would work like this:
51+
52+
1. The application reads the stored devices and creates them using the ``MyProtocol Bridged Device Factory`` class.
53+
#. To bridge new devices, the application needs to know their ``MyProtocol`` connection details.
54+
Those details can be provided by the user or obtained through device discovery.
55+
To enable this, implement the necessary shell commands in the :file:`src/bridge_shell.cpp` file.
56+
#. Using the ``MyProtocol Bridged Device Factory`` class and knowing the connection details, the application creates and stores new bridged devices.
57+
You can use the ``MyProtocol Connectivity Manager`` class to map the ``MyProtocol`` device ID to the corresponding ``MyProtocol Device Data Provider`` instance.
58+
#. Matter traffic is routed through the ``MyProtocol MyDevice Data Provider`` class.
59+
When data from the device is received, you can use the ``MyProtocol Connectivity Manager`` class to forward the data to the correct ``MyProtocol MyDevice Data Provider`` instance.
60+
#. If a device must be removed, the ``MyProtocol Bridged Device Factory`` class handles it.

applications/matter_bridge/src/app_task.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
#include "app/matter_init.h"
1616
#include "app/task_executor.h"
1717
#include "board/board.h"
18-
#include "bridge/bridge_manager.h"
19-
#include "bridge/bridge_storage_manager.h"
18+
#include "bridge_manager.h"
19+
#include "bridge_storage_manager.h"
2020

2121
#ifdef CONFIG_BRIDGED_DEVICE_BT
22-
#include "bridge/ble_connectivity_manager.h"
22+
#include "ble_connectivity_manager.h"
2323
#endif
2424

2525
#include <app-common/zap-generated/attributes/Accessors.h>

applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp renamed to applications/matter_bridge/src/ble/ble_bridged_device_factory.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ CHIP_ERROR StoreDevice(MatterBridgedDevice *device, BridgedDeviceDataProvider *p
8787

8888
bridgedDevice.mEndpointId = device->GetEndpointId();
8989
bridgedDevice.mDeviceType = device->GetDeviceType();
90-
bridgedDevice.mUniqueIDLength = strlen(device->GetUniqueID());
90+
bridgedDevice.mUniqueIDLength = strnlen(device->GetUniqueID(),MatterBridgedDevice::kUniqueIDSize);
9191
memcpy(bridgedDevice.mUniqueID, device->GetUniqueID(), bridgedDevice.mUniqueIDLength);
92-
bridgedDevice.mNodeLabelLength = strlen(device->GetNodeLabel());
92+
bridgedDevice.mNodeLabelLength = strnlen(device->GetNodeLabel(),MatterBridgedDevice::kNodeLabelSize);
9393
memcpy(bridgedDevice.mNodeLabel, device->GetNodeLabel(), bridgedDevice.mNodeLabelLength);
9494

9595
/* Fill BT address information as a part of implementation specific user data. */
@@ -235,15 +235,15 @@ BleBridgedDeviceFactory::BridgedDeviceFactory &BleBridgedDeviceFactory::GetBridg
235235
{
236236
auto checkUniqueID = [](const char *uniqueID) {
237237
/* If node uniqueID is provided it must fit the maximum defined length */
238-
if (!uniqueID || (uniqueID && (strlen(uniqueID) < Nrf::MatterBridgedDevice::kUniqueIDSize))) {
238+
if (!uniqueID || (uniqueID && (strnlen(uniqueID,Nrf::MatterBridgedDevice::kUniqueIDSize) < Nrf::MatterBridgedDevice::kUniqueIDSize))) {
239239
return true;
240240
}
241241
return false;
242242
};
243243

244244
auto checkLabel = [](const char *nodeLabel) {
245245
/* If node label is provided it must fit the maximum defined length */
246-
if (!nodeLabel || (nodeLabel && (strlen(nodeLabel) < MatterBridgedDevice::kNodeLabelSize))) {
246+
if (!nodeLabel || (nodeLabel && (strnlen(nodeLabel,Nrf::MatterBridgedDevice::kNodeLabelSize) < MatterBridgedDevice::kNodeLabelSize))) {
247247
return true;
248248
}
249249
return false;

0 commit comments

Comments
 (0)