From e3dabca027f136c6392f384bb5d8ef19930ceda6 Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Tue, 19 Dec 2023 14:09:25 +0100 Subject: [PATCH] applications: Added guide about extending Matter bridge app Added documentation guide that describes how to extend Matter bridge application by adding: * New Matter device type * New Bluetooth LE service * New protocol By the way, some minor bugs were fixed in the bridge core, as they prevented from making it completely generic and adding new device types without core modifications. Signed-off-by: Kamil Kasperczyk --- applications/matter_bridge/README.rst | 11 +- .../doc/adding_ble_bridged_device_service.rst | 261 +++++++++++ .../doc/adding_bridged_matter_device.rst | 411 ++++++++++++++++++ .../doc/adding_bridged_protocol.rst | 20 + .../matter_bridge/doc/extending_bridge.rst | 17 + ...uide.rst => matter_bridge_description.rst} | 142 +++++- .../ble_bridged_device_factory.cpp | 6 +- .../ble_bridged_device_factory.h | 2 +- .../ble_environmental_data_provider.h | 2 - .../matter_bridge/src/bridge_shell.cpp | 2 +- .../bridged_device_types/generic_switch.cpp | 2 - .../src/bridged_device_types/generic_switch.h | 2 +- .../bridged_device_types/humidity_sensor.cpp | 2 - .../bridged_device_types/humidity_sensor.h | 2 +- .../src/bridged_device_types/onoff_light.cpp | 2 - .../src/bridged_device_types/onoff_light.h | 2 +- .../temperature_sensor.cpp | 2 - .../bridged_device_types/temperature_sensor.h | 2 +- .../simulated_bridged_device_factory.cpp | 18 +- .../simulated_bridged_device_factory.h | 2 +- doc/nrf/protocols/matter/overview/bridge.rst | 2 + .../releases/release-notes-changelog.rst | 1 + .../src/bridge/ble_connectivity_manager.cpp | 1 - .../common/src/bridge/bridge_manager.cpp | 2 +- .../matter/common/src/bridge/bridge_manager.h | 2 +- .../common/src/bridge/matter_bridged_device.h | 2 +- .../common/src/bridge/util/bridge_util.h | 4 +- 27 files changed, 862 insertions(+), 62 deletions(-) create mode 100644 applications/matter_bridge/doc/adding_ble_bridged_device_service.rst create mode 100644 applications/matter_bridge/doc/adding_bridged_matter_device.rst create mode 100644 applications/matter_bridge/doc/adding_bridged_protocol.rst create mode 100644 applications/matter_bridge/doc/extending_bridge.rst rename applications/matter_bridge/doc/{matter_bridge_application_guide.rst => matter_bridge_description.rst} (94%) diff --git a/applications/matter_bridge/README.rst b/applications/matter_bridge/README.rst index fea3b4434a5..b8b57a207ce 100644 --- a/applications/matter_bridge/README.rst +++ b/applications/matter_bridge/README.rst @@ -3,18 +3,17 @@ Matter bridge ############# -.. contents:: - :local: - :depth: 2 - -This Matter bridge application demonstrates the usage of the :ref:`Matter ` application layer to build a bridge device. +The Matter bridge application can be used to build a :ref:`bridge ` device using the :ref:`Matter ` application layer. The bridge device allows the use of non-Matter devices in a :ref:`Matter fabric ` by exposing them as Matter endpoints. The devices on the non-Matter side of the Matter bridge are called *bridged devices*. +The Matter bridge device works as a Matter accessory device, meaning it can be paired and controlled remotely over a Matter network built on top of a low-power 802.11ax (Wi-Fi 6) network. + See the subpages for how to use the application and how to extend it. .. toctree:: :maxdepth: 2 :caption: Subpages: - doc/matter_bridge_application_guide + doc/matter_bridge_description + doc/extending_bridge diff --git a/applications/matter_bridge/doc/adding_ble_bridged_device_service.rst b/applications/matter_bridge/doc/adding_ble_bridged_device_service.rst new file mode 100644 index 00000000000..2290a1b2b31 --- /dev/null +++ b/applications/matter_bridge/doc/adding_ble_bridged_device_service.rst @@ -0,0 +1,261 @@ +.. _matter_bridge_app_extending_ble_service: + +Adding support for a new Bluetooth LE service +############################################# + +The Matter Bridge application supports bridging Bluetooth LE devices using :ref:`LED Button Service ` and :ref:`Environmental Sensing Service ` Bluetooth services. +You can also add support for a proprietary Bluetooth LE service, if required by your use case. +The functionality of the added Bluetooth LE service has to be represented by one or more device types available in the :ref:`Matter Data Model `. +For example, the :ref:`LED Button Service ` is represented by the Matter On/Off Light and Matter Generic Switch device types. + +You can bridge the new Bluetooth LE service with one or more Matter device types supported by the Matter Bridge application, or add support for a new Matter device type. +To learn how to add support for new Matter device type in the Matter Bridge application, see the :ref:`matter_bridge_app_extending_matter_device` page. + +You will need to implement the ``Bridged Device Data Provider`` role based on the :ref:`Matter Bridge architecture ` for the newly added Bluetooth LE service. +The following steps show how to add support for a new Bluetooth LE service called ``My Bt Service``. + +1. Include the header file containing the Bluetooth LE service declaration of the :c:struct:`bt_uuid` type in the :file:`app_task.cpp` file. + + .. code-block:: C++ + + #include "my_bt_service.h" + +#. Update the :c:var:`sUuidServices` array in the :file:`app_task.cpp` file to include the Bluetooth LE service UUID. + + .. code-block:: C++ + + static bt_uuid *sUuidMyBtService = BT_UUID_MY_BT_SERVICE; + static bt_uuid *sUuidServices[] = { sUuidLbs, sUuidEs, sUuidMyBtService}; + +#. Implement the ``Bridged Device Data Provider`` role. + + 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. + #. Open the :file:`nrf/samples/matter/common/bridge/ble_bridged_device.h` header file and find the :c:struct:`BLEBridgedDeviceProvider` class constructor. + Note the constructor signature, it will be used in the child class implemented in the next steps. + #. Add a new :c:struct:`MyBtServiceDataProvider` class inheriting :c:struct:`BLEBridgedDeviceProvider`, and implement its constructor in the :file:`my_bt_service_data_provider.cpp` and :file:`my_bt_service_data_provider.h` files. + + .. code-block:: C++ + + #include "ble_bridged_device.h" + #include "ble_connectivity_manager.h" + #include "bridged_device_data_provider.h" + + #include "my_bt_service.h" + + class MyBtServiceDataProvider : public BLEBridgedDeviceProvider { + public: + explicit MyBtServiceDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BLEBridgedDeviceProvider(updateCallback, commandCallback) {} + + }; + + #. Open the :file:`nrf/samples/matter/common/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. + + 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. + #. Edit the :c:struct:`MyBtServiceDataProvider` class in the :file:`my_bt_service_data_provider.h` header file to declare the required methods as follows: + + .. code-block:: C++ + + void Init() override; + void NotifyUpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, + size_t dataSize) override; + CHIP_ERROR UpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) override; + bt_uuid *GetServiceUuid() override; + int ParseDiscoveredData(bt_gatt_dm *discoveredData) override; + + #. Implement the body of the :c:func:`Init` method so that it can prepare the data provider for further operation. + If there are no additional actions to be done before starting the provider, it can be implemented in the :file:`my_bt_service_data_provider.cpp` file as empty. + + .. code-block:: C++ + + void MyBtServiceDataProvider::Init() + { + /* Do nothing in this case */ + } + + #. Implement the body of the :c:func:`NotifyUpdateState` method that shall be called after every data change related to the Matter devices bridged to the Bluetooth LE device using ``My Bt Service``. + It is used to inform the ``Bridge Manager`` and Matter Data Model that an attribute value should be updated. + + To make the method invoke the appropriate callback, edit the :file:`my_bt_service_data_provider.cpp` file as follows: + + .. code-block:: C++ + + void MyBtServiceDataProvider::NotifyUpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, + size_t dataSize) + { + if (mUpdateAttributeCallback) { + mUpdateAttributeCallback(*this, clusterId, attributeId, data, dataSize); + } + } + + #. Implement the body of the :c:func:`UpdateState` method. + This will be called by the ``Bridge Manager`` to inform that data in Matter Data Model was changed and request propagating this information to the Bluetooth LE end device. + + The content of this method depends on the supported Matter device types and the Bluetooth characteristics supported by the specific Bluetooth LE profile. + If the profile supports write operations, the implementation should analyze the Matter :c:var:`clusterId` and :c:var:`attributeId` variables, and perform a Bluetooth GATT write operation to the corresponding Bluetooth characteristic. + Otherwise, the method can be left empty. + + To handle write operations to the Bluetooth LE device, edit the :file:`my_bt_service_data_provider.h` and :file:`my_bt_service_data_provider.cpp` files using the following code snippets: + + - :file:`my_bt_service_data_provider.h`, :c:struct:`MyBtServiceDataProvider` class + + .. code-block:: C++ + + static void NotifyAttributeChange(intptr_t context); + static void GattWriteCallback(bt_conn *conn, uint8_t err, bt_gatt_write_params *params); + bt_gatt_write_params mGattWriteParams{}; + + - :file:`my_bt_service_data_provider.cpp` + + .. code-block:: C++ + + CHIP_ERROR MyBtServiceDataProvider::UpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) { + /* Set all mGattWriteParams fields and copy data from the input to mGattWriteParams buffer. */ + /* ... */ + mGattWriteParams.func = MyBtServiceDataProvider::GattWriteCallback; + + int err = bt_gatt_write(mDevice.mConn, &mGattWriteParams); + if (err) { + return CHIP_ERROR_INTERNAL; + } + } + + void MyBtServiceDataProvider::GattWriteCallback(bt_conn *conn, uint8_t err, bt_gatt_write_params *params) + { + if (!params) { + return; + } + MyBtServiceDataProvider *provider = static_cast( + BLEConnectivityManager::Instance().FindBLEProvider(*bt_conn_get_dst(conn))); + if (!provider) { + return; + } + + /* Save data received in GATT write response. */ + /* ... */ + DeviceLayer::PlatformMgr().ScheduleWork(NotifyAttributeChange, reinterpret_cast(provider)); + } + + void MyBtServiceDataProvider::NotifyAttributeChange(intptr_t context) + { + MyBtServiceDataProvider *provider = reinterpret_cast(context); + /* Invoke provider->NotifyUpdateState() method to inform the `Bridge Manager` that write operation suceeded and Matter Data Model state can be updated. */ + /* ... */ + } + + #. Implement the body of the :c:func:`GetServiceUuid` method. + This shall return the UUID of the ``My Bt Service`` Bluetooth LE service. + To do this, edit the :file:`my_bt_service_data_provider.cpp` file as follows: + + .. code-block:: C++ + + static bt_uuid *sServiceUuid = BT_UUID_MY_BT_SERVICE; + bt_uuid *MyBtServiceDataProvider::GetServiceUuid() + { + return sServiceUuid; + } + + #. Implement the body of the :c:func:`ParseDiscoveredData` method. + This should parse the input data and save the required Bluetooth characteristic handles for further use. + + The Bluetooth LE service can support different sets of characteristics, so the method content will depend on this set. + Additionally, the Bluetooth LE service might support subscriptions through the GATT CCC characteristic. + In that case, the method implementation should establish a subscription session with the Bluetooth LE end device. + + For example, to handle a single characteristic that additionally supports subscriptions, edit the :file:`my_bt_service_data_provider.h` and :file:`my_bt_service_data_provider.cpp` files as follows: + + - :file:`my_bt_service_data_provider.h`, :c:struct:`MyBtServiceDataProvider` class + + .. code-block:: C++ + + uint16_t mCharacteristicHandle; + uint16_t mCccHandle; + bt_gatt_subscribe_params mGattSubscribeParams{}; + + - :file:`my_bt_service_data_provider.cpp` + + .. code-block:: C++ + + static bt_uuid *sUuidChar = BT_UUID_MY_BT_SERVICE_CHARACTERISTIC; + static bt_uuid *sUuidCcc = BT_UUID_GATT_CCC; + uint8_t MyBtServiceDataProvider::GattNotifyCallback(bt_conn *conn, bt_gatt_subscribe_params *params, const void *data, + uint16_t length) + { + MyBtServiceDataProvider *provider = static_cast( + BLEConnectivityManager::Instance().FindBLEProvider(*bt_conn_get_dst(conn))); + VerifyOrExit(data, ); + VerifyOrExit(provider, ); + + /* Save data received in GATT write response. */ + /* ... */ + DeviceLayer::PlatformMgr().ScheduleWork(NotifyAttributeChange, reinterpret_cast(provider)); + + exit: + return BT_GATT_ITER_CONTINUE; + } + + int MyBtServiceDataProvider::ParseDiscoveredData(bt_gatt_dm *discoveredData) + { + const bt_gatt_dm_attr *gatt_chrc; + const bt_gatt_dm_attr *gatt_desc; + gatt_chrc = bt_gatt_dm_char_by_uuid(discoveredData, sUuidChar); + if (!gatt_chrc) { + return -EINVAL; + } + + gatt_desc = bt_gatt_dm_desc_by_uuid(discoveredData, gatt_chrc, sUuidChar); + if (!gatt_desc) { + return -EINVAL; + } + mCharacteristicHandle = gatt_desc->handle; + + gatt_desc = bt_gatt_dm_desc_by_uuid(discoveredData, gatt_chrc, sUuidCcc); + if (!gatt_desc) { + return -EINVAL; + } + mCccHandle = gatt_desc->handle; + + VerifyOrReturn(mDevice.mConn, LOG_ERR("Invalid connection object")); + + /* Configure subscription for the button characteristic */ + mGattSubscribeParams.ccc_handle = mCccHandle; + mGattSubscribeParams.value_handle = mCharacteristicHandle; + mGattSubscribeParams.value = BT_GATT_CCC_NOTIFY; + mGattSubscribeParams.notify = MyBtServiceDataProvider::GattNotifyCallback; + mGattSubscribeParams.subscribe = nullptr; + mGattSubscribeParams.write = nullptr; + return bt_gatt_subscribe(mDevice.mConn, &mGattSubscribeParams); + } + +#. Add the ``MyBtServiceDataProvider`` implementation created in a previous steps to the compilation process. + To do that, edit the :file:`CMakeLists.txt` file as follows: + + .. code-block:: cmake + + target_sources(app PRIVATE + src/ble_providers/my_bt_service_data_provider.cpp + ) + +#. Provide an allocator for ``MyBtServiceDataProvider`` object creation. + 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. + 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: + + - :file:`ble_bridged_device_factory.h` + + .. code-block:: C++ + + #include "my_bt_service_data_provider.h" + + - :file:`ble_bridged_device_factory.cpp`, :c:func:`GetDataProviderFactory` + + .. code-block:: C++ + + { ServiceUuid::MyBtService, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { + return chip::Platform::New(updateClb, commandClb); + } }, + +#. Provide mapping between the ``My Bt Service`` UUID and corresponding Matter device types in the helper methods. + + a. Add the ``MyBtService`` UUID in the :c:enum:`ServiceUuid` declaration, in the :file:`src/ble_providers/ble_bridged_device_factory.h` header file. + #. 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. + +#. Compile the target and test it following the steps from the :ref:`Matter Bridge application testing ` section. diff --git a/applications/matter_bridge/doc/adding_bridged_matter_device.rst b/applications/matter_bridge/doc/adding_bridged_matter_device.rst new file mode 100644 index 00000000000..6b283b7c1c7 --- /dev/null +++ b/applications/matter_bridge/doc/adding_bridged_matter_device.rst @@ -0,0 +1,411 @@ +.. _matter_bridge_app_extending_matter_device: + +Adding support for a new Matter device type +########################################### + +The Matter Bridge application supports bridging only a few Matter device types due to practical reasons. +However, you can select any of the available :ref:`Matter device types ` and add support to it in the application. + +You will need to implement the ``Matter Bridged Device`` and ``Bridged Device Data Provider`` roles based on the :ref:`Matter Bridge architecture ` for the newly added Matter device type. +The Matter Bridge application supports :ref:`simulated and Bluetooth LE ` bridged device configurations. +In this guide, the simulated provider example is presented, but the process is similar for the Bluetooth LE provider as well. + +The following steps show how to add support for a new Matter device type, using the Pressure Sensor device type as an example. + +1. Enable the ``Pressure Measurement`` cluster for the endpoint ``2`` in the :file:`src/bridge.zap` file and re-generate the files located in the :file:`src/zap-generated` directory. + + To learn how to modify the :file:`.zap` file and re-generate the :file:`zap-generated` directory, see the :ref:`ug_matter_creating_accessory_edit_zap` section in the :ref:`ug_matter_creating_accessory` user guide. +#. Implement the ``Matter Bridged Device`` role. + + a. Create the :file:`pressure_sensor.cpp` and :file:`pressure_sensor.h` files in the :file:`src/bridged_device_types` directory. + #. Open the :file:`nrf/samples/matter/common/bridge/matter_bridged_device.h` header file and find the :c:struct:`MatterBridgedDevice` class constructor. + Note the constructor signature, it will be used in the child class implemented in the next steps. + #. 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. + + - :file:`pressure_sensor.h` + + .. code-block:: C++ + + #pragma once + + #include "matter_bridged_device.h" + + class PressureSensorDevice : public MatterBridgedDevice { + public: + + PressureSensorDevice(const char *nodeLabel); + static constexpr uint16_t kPressureSensorDeviceTypeId = 0x0305; + + }; + + - :file:`pressure_sensor.cpp` + + .. code-block:: C++ + + #include "pressure_sensor.h" + + PressureSensorDevice::PressureSensorDevice(const char *nodeLabel) : MatterBridgedDevice(nodeLabel) {} + + #. 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. + + 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/bridge/matter_bridged_device.h` header file, and the ``Pressure Measurement`` cluster, which has to be defined in the application. + Edit the :file:`pressure_sensor.cpp` file as follows: + + - Add: + + .. code-block:: C++ + + namespace + { + DESCRIPTOR_CLUSTER_ATTRIBUTES(descriptorAttrs); + BRIDGED_DEVICE_BASIC_INFORMATION_CLUSTER_ATTRIBUTES(bridgedDeviceBasicAttrs); + IDENTIFY_CLUSTER_ATTRIBUTES(identifyAttrs); + }; /* namespace */ + using namespace ::chip; + using namespace ::chip::app; + + DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(pressureSensorAttrs) + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::PressureMeasurement::Attributes::MeasuredValue::Id, INT16S, 2, 0), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::PressureMeasurement::Attributes::MinMeasuredValue::Id, INT16S, 2, + 0), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::PressureMeasurement::Attributes::MaxMeasuredValue::Id, INT16S, 2, + 0), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::PressureMeasurement::Attributes::FeatureMap::Id, BITMAP32, 4, 0), + DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); + + DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedPressureClusters) + DECLARE_DYNAMIC_CLUSTER(Clusters::PressureMeasurement::Id, pressureSensorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(Clusters::Descriptor::Id, descriptorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(Clusters::BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(SERVER), sIdentifyIncomingCommands, + nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; + + DECLARE_DYNAMIC_ENDPOINT(bridgedPressureEndpoint, bridgedPressureClusters); + + static constexpr uint8_t kBridgedPressureEndpointVersion = 2; + + static constexpr EmberAfDeviceType kBridgedPressureDeviceTypes[] = { + { static_cast(PressureSensorDevice::kPressureSensorDeviceTypeId), + kBridgedPressureEndpointVersion }, + { static_cast(MatterBridgedDevice::DeviceType::BridgedNode), + MatterBridgedDevice::kDefaultDynamicEndpointVersion } + }; + + static constexpr uint8_t kPressureDataVersionSize = ArraySize(bridgedPressureClusters); + + - Modify the constructor: + + .. code-block:: C++ + + PressureSensorDevice::PressureSensorDevice(const char *nodeLabel) : MatterBridgedDevice(nodeLabel) + { + mDataVersionSize = kPressureDataVersionSize; + mEp = &bridgedPressureEndpoint; + mDeviceTypeList = kBridgedPressureDeviceTypes; + mDeviceTypeListSize = ARRAY_SIZE(kBridgedPressureDeviceTypes); + mDataVersion = static_cast(chip::Platform::MemoryAlloc(sizeof(DataVersion) * mDataVersionSize)); + } + + #. Open the :file:`nrf/samples/matter/common/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. + #. Edit the :c:struct:`PressureSensorDevice` class in the :file:`pressure_sensor.h` header file to declare the required methods as follows: + + .. code-block:: C++ + + uint16_t GetDeviceType() const override; + + CHIP_ERROR HandleRead(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer, + uint16_t maxReadLength) override; + CHIP_ERROR HandleWrite(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) override; + CHIP_ERROR HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, + size_t dataSize) override; + + #. Implement the body of the :c:func:`GetDeviceType` method so that it can return the device type ID for the Pressure Sensor device type, which is equal to ``0x0305``. + To check the device type ID for specific type of device, see Matter Device Library Specification. + + Edit the :file:`pressure_sensor.cpp` file as follows: + + .. code-block:: C++ + + uint16_t PressureSensorDevice::GetDeviceType() const { + return PressureSensorDevice::kPressureSensorDeviceTypeId; + } + + #. Implement the body of the :c:func:`HandleRead` method to handle reading data operations for all supported attributes. + + The read operations for the ``Descriptor``, ``Bridged Device Basic Information`` and ``Identify`` clusters, which are common to all devices, are handled in a common bridge module. + The read operations for the ``Pressure Measurement`` cluster are the only ones to that need to be handled in the application. + + To provide support for reading attributes for the Pressure Sensor device, edit the :file:`pressure_sensor.h` and :file:`pressure_sensor.cpp` files as follows: + + - :file:`pressure_sensor.h`, :c:struct:`PressureSensorDevice` class + + .. code-block:: C++ + + int16_t GetMeasuredValue() { return mMeasuredValue; } + int16_t GetMinMeasuredValue() { return 95; } + int16_t GetMaxMeasuredValue() { return 101; } + uint16_t GetPressureMeasurementClusterRevision() { return 3; } + uint32_t GetPressureMeasurementFeatureMap() { return 0; } + + CHIP_ERROR HandleReadPressureMeasurement(chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength); + uint16_t mMeasuredValue = 0; + + - :file:`pressure_sensor.cpp` + + .. code-block:: C++ + + CHIP_ERROR PressureSensorDevice::HandleRead(ClusterId clusterId, AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) { + switch (clusterId) { + case Clusters::PressureMeasurement::Id: + return HandleReadPressureMeasurement(attributeId, buffer, maxReadLength); + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + } + CHIP_ERROR PressureSensorDevice::HandleReadPressureMeasurement(AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) { + switch (attributeId) { + case Clusters::PressureMeasurement::Attributes::MeasuredValue::Id: { + int16_t value = GetMeasuredValue(); + return CopyAttribute(&value, sizeof(value), buffer, maxReadLength); + } + case Clusters::PressureMeasurement::Attributes::MinMeasuredValue::Id: { + int16_t value = GetMinMeasuredValue(); + return CopyAttribute(&value, sizeof(value), buffer, maxReadLength); + } + case Clusters::PressureMeasurement::Attributes::MaxMeasuredValue::Id: { + int16_t value = GetMaxMeasuredValue(); + return CopyAttribute(&value, sizeof(value), buffer, maxReadLength); + } + case Clusters::PressureMeasurement::Attributes::ClusterRevision::Id: { + uint16_t clusterRevision = GetPressureMeasurementClusterRevision(); + return CopyAttribute(&clusterRevision, sizeof(clusterRevision), buffer, maxReadLength); + } + case Clusters::PressureMeasurement::Attributes::FeatureMap::Id: { + uint32_t featureMap = GetPressureMeasurementFeatureMap(); + return CopyAttribute(&featureMap, sizeof(featureMap), buffer, maxReadLength); + } + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + } + + #. Implement the body of the :c:func:`HandleWrite` method, which handles write data operations for all supported attributes. + In this case, there is no attribute supporting write operations, so edit the :file:`pressure_sensor.cpp` file as follows: + + .. code-block:: C++ + + CHIP_ERROR PressureSensorDevice::HandleWrite(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) { + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + + #. Implement the body of the :c:func:`HandleAttributeChange` method. + This will be called by the ``Bridge Manager`` to notify that data was changed by the ``Bridged Device Data Provider`` and the local state should be updated. + + Edit the :file:`pressure_sensor.h` and :file:`pressure_sensor.cpp` files as follows: + + - :file:`pressure_sensor.h` + + .. code-block:: C++ + + void SetMeasuredValue(int16_t value) { mMeasuredValue = value; } + + - :file:`pressure_sensor.cpp` + + .. code-block:: C++ + + CHIP_ERROR PressureSensorDevice::HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, size_t dataSize) + { + CHIP_ERROR err = CHIP_NO_ERROR; + if (!data) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + switch (clusterId) { + case Clusters::BridgedDeviceBasicInformation::Id: + return HandleWriteDeviceBasicInformation(clusterId, attributeId, data, dataSize); + case Clusters::Identify::Id: + return HandleWriteIdentify(attributeId, data, dataSize); + case Clusters::PressureMeasurement::Id: { + switch (attributeId) { + case Clusters::PressureMeasurement::Attributes::MeasuredValue::Id: { + int16_t value; + + err = CopyAttribute(data, dataSize, &value, sizeof(value)); + + if (err != CHIP_NO_ERROR) { + return err; + } + + SetMeasuredValue(value); + + break; + } + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + break; + } + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return err; + } + +#. Implement the ``Bridged Device Data Provider`` role. + + 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. + #. Open the :file:`nrf/samples/matter/common/bridge/bridged_device_data_provider.h` header file and find the :c:struct:`BridgedDeviceDataProvider` class constructor. + Note the constructor signature, it will be used in the child class implemented in the next steps. + #. 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. + + .. code-block:: C++ + + #pragma once + + #include "bridged_device_data_provider.h" + + #include + + class SimulatedPressureSensorDataProvider : public BridgedDeviceDataProvider { + public: + SimulatedPressureSensorDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BridgedDeviceDataProvider(updateCallback, commandCallback) {} + ~SimulatedPressureSensorDataProvider() {} + }; + + #. Open the :file:`nrf/samples/matter/common/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. + #. Edit the :c:struct:`SimulatedPressureSensorDataProvider` class in the :file:`simulated_pressure_sensor_data_provider.h` header file to declare the required methods as follows: + + .. code-block:: C++ + + void Init() override; + void NotifyUpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, size_t dataSize) override; + CHIP_ERROR UpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) override; + + #. Implement the body of the :c:func:`Init` method so that it can prepare the data provider for further operation. + In this case, the pressure measurements will be simulated by changing data in a random manner and updating it at fixed time intervals. + + To initialize the timer and perform measurement updates, edit the :file:`simulated_pressure_sensor_data_provider.h` and :file:`simulated_pressure_sensor_data_provider.cpp` files as follows: + + - :file:`simulated_pressure_sensor_data_provider.h`, :c:struct:`SimulatedPressureSensorDataProvider` class + + .. code-block:: C++ + + static void NotifyAttributeChange(intptr_t context); + + static constexpr uint16_t kMeasurementsIntervalMs = 10000; + static constexpr int16_t kMinRandomPressure = 95; + static constexpr int16_t kMaxRandomPressure = 101; + + static void TimerTimeoutCallback(k_timer *timer); + k_timer mTimer; + int16_t mPressure = 0; + + - :file:`simulated_pressure_sensor_data_provider.cpp` + + .. code-block:: C++ + + #include "simulated_pressure_sensor_data_provider.h" + + using namespace ::chip; + using namespace ::chip::app; + + void SimulatedPressureSensorDataProvider::Init() + { + k_timer_init(&mTimer, SimulatedPressureSensorDataProvider::TimerTimeoutCallback, nullptr); + k_timer_user_data_set(&mTimer, this); + k_timer_start(&mTimer, K_MSEC(kMeasurementsIntervalMs), K_MSEC(kMeasurementsIntervalMs)); + } + + void SimulatedPressureSensorDataProvider::TimerTimeoutCallback(k_timer *timer) + { + if (!timer || !timer->user_data) { + return; + } + SimulatedPressureSensorDataProvider *provider = reinterpret_cast(timer->user_data); + /* Get some random data to emulate sensor measurements. */ + provider->mPressure = chip::Crypto::GetRandU16() % (kMaxRandomPressure - kMinRandomPressure) + kMinRandomPressure; + DeviceLayer::PlatformMgr().ScheduleWork(NotifyAttributeChange, reinterpret_cast(provider)); + } + + void SimulatedPressureSensorDataProvider::NotifyAttributeChange(intptr_t context) + { + SimulatedPressureSensorDataProvider *provider = reinterpret_cast(context); + provider->NotifyUpdateState(Clusters::PressureMeasurement::Id, + Clusters::PressureMeasurement::Attributes::MeasuredValue::Id, + &provider->mPressure, sizeof(provider->mPressure)); + } + + #. Implement the body of the :c:func:`NotifyUpdateState` method that shall be called after every data change related to the Pressure Sensor device. + It is used to inform the ``Bridge Manager`` and Matter Data Model that an attribute value should be updated. + + To make the method invoke the appropriate callback, edit the :file:`simulated_pressure_sensor_data_provider.cpp` file as follows: + + .. code-block:: C++ + + void SimulatedPressureSensorDataProvider::NotifyUpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, + void *data, size_t dataSize) + { + if (mUpdateAttributeCallback) { + mUpdateAttributeCallback(*this, Clusters::PressureMeasurement::Id, + Clusters::PressureMeasurement::Attributes::MeasuredValue::Id, data, + dataSize); + } + } + + #. Implement the body of the :c:func:`UpdateState` method. + This will be called by the ``Bridge Manager`` to inform that data in Matter Data Model was changed and request propagating this information to the end device. + + In this case, there is no attribute supporting write operations and sending data to end device is not required, so edit the :file:`simulated_pressure_sensor_data_provider.cpp` file as follows: + + .. code-block:: C++ + + CHIP_ERROR SimulatedPressureSensorDataProvider::UpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t *buffer) + { + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + +#. Add the ``PressureSensorDevice`` and ``SimulatedPressureSensorDataProvider`` implementations created in previous steps to the compilation process. + To do that, edit the :file:`CMakeLists.txt` file as follows: + + .. code-block:: cmake + + target_sources(app PRIVATE + src/bridged_device_types/pressure_sensor.cpp + src/simulated_providers/simulated_pressure_sensor_data_provider.cpp + ) + +#. Provide allocators for ``PressureSensorDevice`` and ``SimulatedPressureSensorDataProvider`` object creation. + The Matter Bridge application uses a :c:struct:`SimulatedBridgedDeviceFactory` factory module that creates paired ``Matter Bridged Device`` and ``Bridged Device Data Provider`` objects matching a specific Matter device type ID. + + To add support for creating the ``PressureSensorDevice`` and ``SimulatedPressureSensorDataProvider`` objects when the Pressure Sensor device type ID is used, edit the :file:`src/simulated_providers/simulated_bridged_device_factory.h` and :file:`src/simulated_providers/simulated_bridged_device_factory.cpp` files as follows: + + - :file:`src/simulated_providers/simulated_bridged_device_factory.h` + + .. code-block:: C++ + + #include "pressure_sensor.h" + #include "simulated_pressure_sensor_data_provider.h" + + - :file:`src/simulated_providers/simulated_bridged_device_factory.h`, :c:func:`GetBridgedDeviceFactory` method + + .. code-block:: C++ + + { PressureSensorDevice::kPressureSensorDeviceTypeId, + [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { + if (!checkLabel(nodeLabel)) { + return nullptr; + } + return chip::Platform::New(nodeLabel); + } }, + + - :file:`src/simulated_providers/simulated_bridged_device_factory.h`, :c:func:`GetDataProviderFactory` method + + .. code-block:: C++ + + { PressureSensorDevice::kPressureSensorDeviceTypeId, + [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { + return chip::Platform::New(updateClb, commandClb); + } }, + +5. Compile the target and test it following the steps from the :ref:`Matter Bridge application testing ` section. diff --git a/applications/matter_bridge/doc/adding_bridged_protocol.rst b/applications/matter_bridge/doc/adding_bridged_protocol.rst new file mode 100644 index 00000000000..8a1bd20b6f3 --- /dev/null +++ b/applications/matter_bridge/doc/adding_bridged_protocol.rst @@ -0,0 +1,20 @@ +.. _matter_bridge_app_extending_protocol: + +Adding support for a proprietary protocol +######################################### + +The :ref:`Matter Bridge architecture ` describes the two sides of bridging relationship, ``Matter Bridged Device`` and ``Bridged Device Data Provider``. +The ``Matter Bridged Device`` represents the side that natively supports Matter, and the ``Bridged Device Data Provider`` represents a non-Matter interface. +It is not specified what protocol should be used for a ``Bridged Device Data Provider`` role. + +The Matter Bridge application supports bridging Matter to Bluetooth LE data providers that use the Bluetooth LE protocol to communicate with physical end devices, and simulated data providers that emulate real devices behavior in the application. +You can add support for any protocol as long as you are able to describe data model translation between Matter and that protocol. + +To provide support for a new protocol, you have to implement the ``Bridged Device Data Provider`` role that is able to communicate with the physical end devices using that protocol. +The interactions to be implemented by the ``Bridged Device Data Provider`` vary depending on the bridged Matter device type. + +Typically the ``Bridged Device Data Provider`` has to provide up-to-date information about the device's state by pushing notification about the state changes. +This allows updating the Matter Data Model state and also enables handling Matter subscriptions. +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. + +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. diff --git a/applications/matter_bridge/doc/extending_bridge.rst b/applications/matter_bridge/doc/extending_bridge.rst new file mode 100644 index 00000000000..eff6b9e6df9 --- /dev/null +++ b/applications/matter_bridge/doc/extending_bridge.rst @@ -0,0 +1,17 @@ +.. _matter_bridge_app_extending: + +Extending the application +######################### + +The Matter Bridge application presents an example implementation that supports only a few bridged device types. +You can use the application as a reference for creating your own, but might need to extend or customize it to fulfill all your requirements. + +This following subpages describe and introduce the modifications for their respective scenarios. + +.. toctree:: + :maxdepth: 2 + :caption: Subpages: + + adding_bridged_matter_device + adding_ble_bridged_device_service + adding_bridged_protocol diff --git a/applications/matter_bridge/doc/matter_bridge_application_guide.rst b/applications/matter_bridge/doc/matter_bridge_description.rst similarity index 94% rename from applications/matter_bridge/doc/matter_bridge_application_guide.rst rename to applications/matter_bridge/doc/matter_bridge_description.rst index 1631779114c..0145c8322ab 100644 --- a/applications/matter_bridge/doc/matter_bridge_application_guide.rst +++ b/applications/matter_bridge/doc/matter_bridge_description.rst @@ -1,19 +1,19 @@ -.. _matter_bridge_application_guide: +.. _matter_bridge_app_description: -Matter bridge application guide -******************************* +Application guide +################# .. contents:: :local: :depth: 2 -The Matter bridge device works as a Matter accessory device, meaning it can be paired and controlled remotely over a Matter network built on top of a low-power 802.11ax (Wi-Fi 6) network. +The Matter bridge application demonstrates how to use the :ref:`Matter ` application layer to build a bridge device. You can use this application as a reference for creating your own application. -See :ref:`ug_matter_overview_bridge` for more information about the Matter bridge specification and architecture. +See the :ref:`ug_matter_overview_bridge` page for more information about the Matter bridge specification and architecture. Requirements -============ +************ The application supports the following development kits: @@ -26,7 +26,7 @@ To test the Matter bridge application with the :ref:`Bluetooth LE bridged device * :ref:`peripheral_lbs` * :ref:`peripheral_esp` -* A micro-USB cable to connect the development kit to the PC. +* A micro-USB cable for every development kit to connect it to the PC. To commission the Matter bridge device and control it remotely through a Wi-Fi network, you also need a Matter controller device :ref:`configured on PC or smartphone `. This requires additional hardware depending on your setup. @@ -37,7 +37,7 @@ This requires additional hardware depending on your setup. .. _matter_bridge_app_overview: Overview -======== +******** The application uses buttons to control the device state and a single LED to show the state of a device. The Matter bridge has capability of representing non-Matter bridged devices as dynamic endpoints. @@ -49,6 +49,9 @@ The application supports bridging the following Matter device types: * Temperature Sensor * Humidity Sensor +If the Matter device type required by your use case is not supported, you can extend the application. +For information about how to add a new bridged Matter device type to the application, see the :ref:`matter_bridge_app_extending` section. + Except for the On/Off Light Switch, all of the listed device types are enabled by default. To disable one of them, set any of the following configuration options: @@ -83,12 +86,16 @@ When building on the command line, run the following command: .. parsed-literal:: :class: highlight + west build -b *build_target* -- *dfu_build_flag* + Replace *build_target* with the build target name of the hardware platform you are using (see `Requirements`_), and *dfu_build_flag* with the desired DFU build flag. For example: .. code-block:: console + west build -b nrf7002dk_nrf5340_cpuapp -- -DCONFIG_CHIP_DFU_OVER_BT_SMP=y + For information about how to upgrade the device firmware using a PC or a smartphone, see the :ref:`matter_bridge_app_dfu` section. .. _matter_bridge_app_bridged_support: @@ -106,6 +113,9 @@ The application supports two bridged device configurations that are mutually exc The service can be configured to use the On/Off Light Switch instead of the Generic Switch device type. * Zephyr's :ref:`Environmental Sensing Service ` - represented by the Matter Temperature Sensor and Humidity Sensor device types. +If the Bluetooth LE service required by your use case is not supported, you can extend the application. +For information about how to add a new Bluetooth LE service support to the application, see the :ref:`matter_bridge_app_extending_ble_service` section. + Depending on the bridged device you want to support in your application, :ref:`enable it using the appropriate Kconfig option `. The Matter bridge supports adding and removing bridged devices dynamically at application runtime using `Matter CLI commands`_ from a dedicated Matter bridge shell module. @@ -151,25 +161,30 @@ This sample supports the following build types: The ``debug`` build type is used by default if no build type is explicitly selected. User interface -============== +************** -.. include:: ../../samples/matter/lock/README.rst +.. include:: ../../../samples/matter/lock/README.rst :start-after: matter_door_lock_sample_led1_start :end-before: matter_door_lock_sample_led1_end Button 1: Depending on how long you press the button: - * If pressed for less than three seconds, it initiates the SMP server (Simple Management Protocol). - After that, the Direct Firmware Update (DFU) over Bluetooth Low Energy can be started. - (See `Updating the device firmware`_.) + * If pressed for less than three seconds: + + * If the device is not provisioned to the Matter network, it initiates the SMP server (Simple Management Protocol) and Bluetooth LE advertising for Matter commissioning. + After that, the Direct Firmware Update (DFU) over Bluetooth Low Energy can be started. + (See `Updating the device firmware`_.) + Bluetooth LE advertising makes the device discoverable over Bluetooth LE for the predefined period of time (15 minutes by default). + + * If the device is already provisioned to the Matter network it re-enables the SMP server. + After that, the DFU over Bluetooth Low Energy can be started. + (See `Updating the device firmware`_.) + * If pressed for more than three seconds, it initiates the factory reset of the device. Releasing the button within a 3-second window of the initiation cancels the factory reset procedure. -Button 2: - Enables Bluetooth LE advertising for the predefined period of time (15 minutes by default), and makes the device discoverable over Bluetooth LE. - -.. include:: ../../samples/matter/lock/README.rst +.. include:: ../../../samples/matter/lock/README.rst :start-after: matter_door_lock_sample_jlink_start :end-before: matter_door_lock_sample_jlink_end @@ -184,22 +199,28 @@ Getting a list of Bluetooth LE devices available to be added Use the following command: .. code-block:: console + matter_bridge scan + The terminal output is similar to the following one: .. code-block:: console + Scan result: --------------------------------------------------------------------- | Index | Address | UUID --------------------------------------------------------------------- | 0 | e6:11:40:96:a0:18 | 0x181a (Environmental Sensing Service) | 1 | c7:44:0f:3e:bb:f0 | 0xbcd1 (Led Button Service) + Adding a simulated bridged device to the Matter bridge Use the following command: .. parsed-literal:: :class: highlight + matter_bridge add ** *["node_label"]* + In this command: * ** is the Matter device type to use for the bridged device. @@ -217,13 +238,17 @@ Adding a simulated bridged device to the Matter bridge Example command: .. code-block:: console + uart:~$ matter_bridge add 256 "Kitchen Light" + Controlling a simulated On/Off Light bridged device Use the following command: .. parsed-literal:: :class: highlight + matter_bridge onoff ** ** + In this command: * ** is the new state (``0`` - off and ``1`` - on) that will be set on the simulated On/Off Light device. @@ -232,7 +257,9 @@ Controlling a simulated On/Off Light bridged device Example command: .. code-block:: console + uart:~$ matter_bridge onoff 1 3 + Note that the above command will only work if the :kconfig:option:`CONFIG_BRIDGED_DEVICE_SIMULATED_ONOFF_SHELL` option is selected in the build configuration. If the Kconfig option is not selected, the simulated device changes its state periodically in autonomous manner and can not be controlled by using shell commands. @@ -241,7 +268,9 @@ Controlling a simulated On/Off Light Switch bridged device .. parsed-literal:: :class: highlight + matter_bridge onoff_switch ** ** + In this command: * ** is the new state (``0`` - off and ``1`` - on) that will be set on the simulated On/Off Light Switch device. @@ -250,13 +279,18 @@ Controlling a simulated On/Off Light Switch bridged device Example command: .. code-block:: console + uart:~$ matter_bridge onoff_switch 1 3 + + Adding a Bluetooth LE bridged device to the Matter bridge Use the following command: .. parsed-literal:: :class: highlight + matter_bridge add ** *["node label"]* + In this command: * ** is the Bluetooth LE device index on the list returned by the ``scan`` command. @@ -268,28 +302,37 @@ Adding a Bluetooth LE bridged device to the Matter bridge Example command: .. code-block:: console + uart:~$ matter_bridge add 0 "Kitchen Light" + The terminal output is similar to the following one: .. code-block:: console + I: Added device to dynamic endpoint 3 (index=0) I: Added device to dynamic endpoint 4 (index=1) I: Created 0x100 device type on the endpoint 3 I: Created 0xf device type on the endpoint 4 + + Removing a bridged device from the Matter bridge Use the following command: .. parsed-literal:: :class: highlight + matter_bridge remove ** + In this command, ** is the endpoint ID of the bridged device to be removed. Example command: .. code-block:: console + uart:~$ matter_bridge remove 3 + Configuration -============= +************* |config| @@ -334,11 +377,13 @@ Build the target using the following command in the project directory to enable .. parsed-literal:: :class: highlight + west build -b nrf7002dk_nrf5340_cpuapp -- -DCONFIG_BRIDGED_DEVICE_BT=y -DOVERLAY_CONFIG="overlay-bt_max_connections_app.conf" -Dhci_rpmsg_OVERLAY_CONFIG="*absoule_path*/overlay-bt_max_connections_net.conf" + Replace *absolute_path* with the absolute path to the Matter bridge application on your local disk. Building and running -==================== +******************** .. |sample path| replace:: :file:`applications/matter_bridge` @@ -367,7 +412,9 @@ For example, you can replace the *selected_build_type* variable to build the ``r .. parsed-literal:: :class: highlight + west build -b nrf7002dk_nrf5340_cpuapp -d build_nrf7002dk_nrf5340_cpuapp -- -DCONF_FILE=prj_release.conf + The ``build_nrf7002dk_nrf5340_cpuapp`` parameter specifies the output directory for the build files. .. note:: @@ -375,7 +422,11 @@ The ``build_nrf7002dk_nrf5340_cpuapp`` parameter specifies the output directory For example, if the ``shell`` build type is not supported by the selected board, the following notification appears: .. code-block:: console + File not found: ./ncs/nrf/applications/matter_bridge/configuration/nrf7002dk_nrf5340_cpuapp/prj_shell.conf + +.. _matter_bridge_testing: + Testing ======= @@ -399,18 +450,24 @@ After building the sample and programming it to your development kit, complete t .. parsed-literal:: :class: highlight + uart:~$ matter_bridge add ** + The ** is the value of the Matter device type that will be used to represent a new bridged device in the Matter Data Model. See the description in :ref:`matter_bridge_cli` for the list of supported values. For example, if you want to add a new bridged device that will be exposed as an On/Off Light endpoint, use the following command: .. code-block:: console + uart:~$ matter_bridge add 256 + The terminal output is similar to the following one: .. code-block:: console + I: Adding OnOff Light bridged device I: Added device to dynamic endpoint 3 (index=0) + #. Write down the value for the bridged device dynamic endpoint ID. This is going to be used in the next steps (**). #. Use the :doc:`CHIP Tool ` to read the value of an attribute from the bridged device endpoint. @@ -418,7 +475,9 @@ After building the sample and programming it to your development kit, complete t .. parsed-literal:: :class: highlight + ./chip-tool onoff read on-off ** ** + .. group-tab:: Testing with Bluetooth LE bridged devices a. Build and program the one of the following Bluetooth LE samples to an additional development kit compatible with the sample: @@ -430,36 +489,46 @@ After building the sample and programming it to your development kit, complete t #. Using the terminal emulator connected to the bridge, run the following :ref:`Matter CLI command ` to scan for available Bluetooth LE devices: .. code-block:: console + uart:~$ matter_bridge scan + The terminal output is similar to the following one, with an entry for each connected Bluetooth LE device: .. code-block:: console + Scan result: --------------------------------------------------------------------- | Index | Address | UUID --------------------------------------------------------------------- | 0 | e6:11:40:96:a0:18 | 0x181a (Environmental Sensing Service) | 1 | c7:44:0f:3e:bb:f0 | 0xbcd1 (Led Button Service) + #. Write down the value for the desired Bluetooth LE device index. This is going to be used in the next steps (**). #. Using the terminal emulator connected to the bridge, run the following :ref:`Matter CLI command ` to add a new bridged device: .. parsed-literal:: :class: highlight + uart:~$ matter_bridge add ** + The ** is a Bluetooth LE device index that was scanned in the previous step. For example, if you want to add a new Bluetooth LE bridged device with index ``1``, use the following command: .. code-block:: console + uart:~$ matter_bridge add 1 + The terminal output is similar to the following one: .. parsed-literal:: :class: highlight + I: Added device to dynamic endpoint 3 (index=0) I: Added device to dynamic endpoint 4 (index=1) I: Created 0x100 device type on the endpoint 3 I: Created 0xf device type on the endpoint 4 + For the LED Button Service and the Environmental Sensor, two endpoints are created: * For the LED Button Service, one implements the On/Off Light device and the other implements the Generic Switch or On/Off Light Switch device. @@ -472,12 +541,17 @@ After building the sample and programming it to your development kit, complete t .. parsed-literal:: :class: highlight + ./chip-tool onoff read on-off ** ** + + If you are using the Generic Switch implementation, read the value of the *current-position* attribute from the *switch* cluster using the following command: .. parsed-literal:: :class: highlight + ./chip-tool switch read current-position ** ** + Note that the Generic Switch is implemented as a momentary switch. This means that, in contrast to the latching switch, it remains switched on only as long as the physical button is pressed. @@ -487,12 +561,16 @@ After building the sample and programming it to your development kit, complete t .. parsed-literal:: :class: highlight + ./chip-tool temperaturemeasurement read measured-value ** ** + * humidity: .. parsed-literal:: :class: highlight + ./chip-tool relativehumiditymeasurement read measured-value ** ** + Testing with bridged device working as a client ----------------------------------------------- @@ -519,12 +597,16 @@ After building this application and the :ref:`Matter Light Bulb *). @@ -535,35 +617,45 @@ After building this application and the :ref:`Matter Light Bulb ` to scan for available Bluetooth LE devices: .. code-block:: console + uart:~$ matter_bridge scan + The terminal output is similar to the following one, with an entry for each connected Bluetooth LE device: .. code-block:: console + Scan result: --------------------------------------------------------------------- | Index | Address | UUID --------------------------------------------------------------------- | 0 | c7:44:0f:3e:bb:f0 | 0xbcd1 (Led Button Service) + #. Write down the value for the desired Bluetooth LE device index. This is going to be used in the next steps (**). #. Using the terminal emulator connected to the bridge, run the following :ref:`Matter CLI command ` to add a new bridged device: .. parsed-literal:: :class: highlight + uart:~$ matter_bridge add ** + The ** is the Bluetooth LE device index that was scanned in the previous step. For example, if you want to add a new Bluetooth LE bridged device with index ``0``, use the following command: .. code-block:: console + uart:~$ matter_bridge add 0 + The terminal output is similar to the following one: .. parsed-literal:: :class: highlight + I: Added device to dynamic endpoint 3 (index=0) I: Added device to dynamic endpoint 4 (index=1) I: Created 0x100 device type on the endpoint 3 I: Created 0x103 device type on the endpoint 4 + #. Write down the value for the ``0x103`` bridged device dynamic endpoint ID. This is going to be used in the next steps (**). @@ -572,12 +664,16 @@ After building this application and the :ref:`Matter Light Bulb *], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}]' ** 0 + #. Write a binding table to the bridge to inform the device about all endpoints by running the following command: .. parsed-literal:: :class: highlight + chip-tool binding write binding '[{"fabricIndex": 1, "node": **, "endpoint": 1, "cluster": 6}]' ** ** + #. Complete the following steps depending on your configuration: .. tabs:: @@ -588,12 +684,16 @@ After building this application and the :ref:`Matter Light Bulb * + #. Using the terminal emulator connected to the bridge, turn off the **LED 2** located on the bound light bulb device, by running the following :ref:`Matter CLI command `: .. parsed-literal:: :class: highlight + uart:~$ matter_bridge onoff_switch 0 ** + .. group-tab:: Testing with Bluetooth LE bridged light switch device a. On the Peripheral LBS device, press **Button 1** to turn on the **LED 2** located on the bound light bulb device. @@ -653,7 +753,7 @@ Updating the device firmware To update the device firmware, complete the steps listed for the selected method in the :doc:`matter:nrfconnect_examples_software_update` tutorial in the Matter documentation. Dependencies -============ +************ This application uses the Matter library, which includes the |NCS| platform integration layer: @@ -668,4 +768,4 @@ In addition, the application uses the following |NCS| components: The application depends on the following Zephyr libraries: * :ref:`zephyr:logging_api` -* :ref:`zephyr:kernel_api` \ No newline at end of file +* :ref:`zephyr:kernel_api` diff --git a/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp b/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp index a23d5ae232f..f176814603e 100644 --- a/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp +++ b/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp @@ -229,7 +229,7 @@ BleBridgedDeviceFactory::BridgedDeviceFactory &BleBridgedDeviceFactory::GetBridg static BridgedDeviceFactory sBridgedDeviceFactory{ #ifdef CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE - { DeviceType::HumiditySensor, + { MatterBridgedDevice::DeviceType::HumiditySensor, [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; @@ -238,7 +238,7 @@ BleBridgedDeviceFactory::BridgedDeviceFactory &BleBridgedDeviceFactory::GetBridg } }, #endif #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_BRIDGED_DEVICE - { DeviceType::OnOffLight, + { MatterBridgedDevice::DeviceType::OnOffLight, [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; @@ -265,7 +265,7 @@ BleBridgedDeviceFactory::BridgedDeviceFactory &BleBridgedDeviceFactory::GetBridg } }, #endif #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE - { DeviceType::OnOffLightSwitch, + { MatterBridgedDevice::DeviceType::OnOffLightSwitch, [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; diff --git a/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.h b/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.h index 9158f570056..67c1194da98 100644 --- a/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.h +++ b/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.h @@ -48,7 +48,7 @@ enum ServiceUuid : uint16_t { LedButtonService = 0xbcd1, EnvironmentalSensorServ using UpdateAttributeCallback = BridgedDeviceDataProvider::UpdateAttributeCallback; using InvokeCommandCallback = BridgedDeviceDataProvider::InvokeCommandCallback; -using DeviceType = MatterBridgedDevice::DeviceType; +using DeviceType = uint16_t; using BridgedDeviceFactory = DeviceFactory; using BleDataProviderFactory = DeviceFactory; diff --git a/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.h b/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.h index 4e2b73e3722..f121e40a5ba 100644 --- a/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.h +++ b/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.h @@ -10,8 +10,6 @@ #include "ble_connectivity_manager.h" #include "bridged_device_data_provider.h" -#include - class BleEnvironmentalDataProvider : public BLEBridgedDeviceProvider { public: explicit BleEnvironmentalDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BLEBridgedDeviceProvider(updateCallback, commandCallback) {} diff --git a/applications/matter_bridge/src/bridge_shell.cpp b/applications/matter_bridge/src/bridge_shell.cpp index 89ca5157fac..01e1aaf4b10 100644 --- a/applications/matter_bridge/src/bridge_shell.cpp +++ b/applications/matter_bridge/src/bridge_shell.cpp @@ -91,7 +91,7 @@ static int SimulatedBridgedDeviceOnOffWriteHandler(const struct shell *shell, si uint8_t value = strtoul(argv[1], nullptr, 0); chip::EndpointId endpointId = strtoul(argv[2], nullptr, 0); - DeviceType deviceType{}; + uint16_t deviceType{}; auto *provider = BridgeManager().Instance().GetProvider(endpointId, deviceType); if (provider) { diff --git a/applications/matter_bridge/src/bridged_device_types/generic_switch.cpp b/applications/matter_bridge/src/bridged_device_types/generic_switch.cpp index 0870462c308..67cdf65b500 100644 --- a/applications/matter_bridge/src/bridged_device_types/generic_switch.cpp +++ b/applications/matter_bridge/src/bridged_device_types/generic_switch.cpp @@ -62,8 +62,6 @@ CHIP_ERROR GenericSwitchDevice::HandleRead(ClusterId clusterId, AttributeId attr switch (clusterId) { case Clusters::Switch::Id: return HandleReadSwitch(attributeId, buffer, maxReadLength); - case Clusters::Identify::Id: - return HandleReadIdentify(attributeId, buffer, maxReadLength); default: return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/applications/matter_bridge/src/bridged_device_types/generic_switch.h b/applications/matter_bridge/src/bridged_device_types/generic_switch.h index dd2b05b4491..0fc77daf126 100644 --- a/applications/matter_bridge/src/bridged_device_types/generic_switch.h +++ b/applications/matter_bridge/src/bridged_device_types/generic_switch.h @@ -12,7 +12,7 @@ class GenericSwitchDevice : public MatterBridgedDevice { public: GenericSwitchDevice(const char *nodeLabel); - MatterBridgedDevice::DeviceType GetDeviceType() const override + uint16_t GetDeviceType() const override { return MatterBridgedDevice::DeviceType::GenericSwitch; } diff --git a/applications/matter_bridge/src/bridged_device_types/humidity_sensor.cpp b/applications/matter_bridge/src/bridged_device_types/humidity_sensor.cpp index 894f5385d8b..4d7558f7a89 100644 --- a/applications/matter_bridge/src/bridged_device_types/humidity_sensor.cpp +++ b/applications/matter_bridge/src/bridged_device_types/humidity_sensor.cpp @@ -60,8 +60,6 @@ CHIP_ERROR HumiditySensorDevice::HandleRead(ClusterId clusterId, AttributeId att switch (clusterId) { case Clusters::RelativeHumidityMeasurement::Id: return HandleReadRelativeHumidityMeasurement(attributeId, buffer, maxReadLength); - case Clusters::Identify::Id: - return HandleReadIdentify(attributeId, buffer, maxReadLength); default: return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/applications/matter_bridge/src/bridged_device_types/humidity_sensor.h b/applications/matter_bridge/src/bridged_device_types/humidity_sensor.h index b0f27c55851..c3d5db7c5aa 100644 --- a/applications/matter_bridge/src/bridged_device_types/humidity_sensor.h +++ b/applications/matter_bridge/src/bridged_device_types/humidity_sensor.h @@ -21,7 +21,7 @@ class HumiditySensorDevice : public MatterBridgedDevice { uint16_t GetRelativeHumidityMeasurementClusterRevision() { return kRelativeHumidityMeasurementClusterRevision; } uint32_t GetRelativeHumidityMeasurementFeatureMap() { return kRelativeHumidityMeasurementFeatureMap; } - MatterBridgedDevice::DeviceType GetDeviceType() const override + uint16_t GetDeviceType() const override { return MatterBridgedDevice::DeviceType::HumiditySensor; } diff --git a/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp b/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp index ec8e240ac79..a08d3d2cea4 100644 --- a/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp +++ b/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp @@ -83,8 +83,6 @@ CHIP_ERROR OnOffLightDevice::HandleRead(ClusterId clusterId, AttributeId attribu return HandleReadOnOff(attributeId, buffer, maxReadLength); case Clusters::Groups::Id: return HandleReadGroups(attributeId, buffer, maxReadLength); - case Clusters::Identify::Id: - return HandleReadIdentify(attributeId, buffer, maxReadLength); default: return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/applications/matter_bridge/src/bridged_device_types/onoff_light.h b/applications/matter_bridge/src/bridged_device_types/onoff_light.h index 175c229e3da..50168fc7df9 100644 --- a/applications/matter_bridge/src/bridged_device_types/onoff_light.h +++ b/applications/matter_bridge/src/bridged_device_types/onoff_light.h @@ -25,7 +25,7 @@ class OnOffLightDevice : public MatterBridgedDevice { uint32_t GetGroupsFeatureMap() { return kGroupsFeatureMap; } uint8_t GetGroupsNameSupportMap() { return kGroupsNameSupportMap; } - MatterBridgedDevice::DeviceType GetDeviceType() const override + uint16_t GetDeviceType() const override { return MatterBridgedDevice::DeviceType::OnOffLight; } diff --git a/applications/matter_bridge/src/bridged_device_types/temperature_sensor.cpp b/applications/matter_bridge/src/bridged_device_types/temperature_sensor.cpp index ab0085019a6..d5dbba5eaad 100644 --- a/applications/matter_bridge/src/bridged_device_types/temperature_sensor.cpp +++ b/applications/matter_bridge/src/bridged_device_types/temperature_sensor.cpp @@ -58,8 +58,6 @@ CHIP_ERROR TemperatureSensorDevice::HandleRead(ClusterId clusterId, AttributeId switch (clusterId) { case Clusters::TemperatureMeasurement::Id: return HandleReadTemperatureMeasurement(attributeId, buffer, maxReadLength); - case Clusters::Identify::Id: - return HandleReadIdentify(attributeId, buffer, maxReadLength); default: return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/applications/matter_bridge/src/bridged_device_types/temperature_sensor.h b/applications/matter_bridge/src/bridged_device_types/temperature_sensor.h index 3ba8288f3ca..71408dd690b 100644 --- a/applications/matter_bridge/src/bridged_device_types/temperature_sensor.h +++ b/applications/matter_bridge/src/bridged_device_types/temperature_sensor.h @@ -21,7 +21,7 @@ class TemperatureSensorDevice : public MatterBridgedDevice { uint16_t GetTemperatureMeasurementClusterRevision() { return kTemperatureMeasurementClusterRevision; } uint32_t GetTemperatureMeasurementFeatureMap() { return kTemperatureMeasurementFeatureMap; } - MatterBridgedDevice::DeviceType GetDeviceType() const override + uint16_t GetDeviceType() const override { return MatterBridgedDevice::DeviceType::TemperatureSensor; } diff --git a/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.cpp b/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.cpp index 479eea592b3..267e479cc57 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.cpp +++ b/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.cpp @@ -67,7 +67,7 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto static BridgedDeviceFactory sBridgedDeviceFactory{ #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_BRIDGED_DEVICE - { DeviceType::OnOffLight, + { MatterBridgedDevice::DeviceType::OnOffLight, [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; @@ -76,7 +76,7 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto } }, #endif #ifdef CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE - { DeviceType::GenericSwitch, + { MatterBridgedDevice::DeviceType::GenericSwitch, [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; @@ -85,7 +85,7 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto } }, #endif #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE - { DeviceType::OnOffLightSwitch, + { MatterBridgedDevice::DeviceType::OnOffLightSwitch, [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; @@ -103,7 +103,7 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto } }, #endif #ifdef CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE - { DeviceType::HumiditySensor, + { MatterBridgedDevice::DeviceType::HumiditySensor, [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; @@ -119,31 +119,31 @@ SimulatedBridgedDeviceFactory::SimulatedDataProviderFactory &SimulatedBridgedDev { static SimulatedDataProviderFactory sDeviceDataProvider{ #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_BRIDGED_DEVICE - { DeviceType::OnOffLight, + { MatterBridgedDevice::DeviceType::OnOffLight, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, #endif #ifdef CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE - { DeviceType::GenericSwitch, + { MatterBridgedDevice::DeviceType::GenericSwitch, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, #endif #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE - { DeviceType::OnOffLightSwitch, + { MatterBridgedDevice::DeviceType::OnOffLightSwitch, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, #endif #ifdef CONFIG_BRIDGE_TEMPERATURE_SENSOR_BRIDGED_DEVICE - { DeviceType::TemperatureSensor, + { MatterBridgedDevice::DeviceType::TemperatureSensor, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, #endif #ifdef CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE - { DeviceType::HumiditySensor, + { MatterBridgedDevice::DeviceType::HumiditySensor, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, diff --git a/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.h b/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.h index 380e0184ad9..ffa7de766c3 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.h +++ b/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.h @@ -40,7 +40,7 @@ namespace SimulatedBridgedDeviceFactory { using UpdateAttributeCallback = BridgedDeviceDataProvider::UpdateAttributeCallback; using InvokeCommandCallback = BridgedDeviceDataProvider::InvokeCommandCallback; -using DeviceType = MatterBridgedDevice::DeviceType; +using DeviceType = uint16_t; using BridgedDeviceFactory = DeviceFactory; using SimulatedDataProviderFactory = DeviceFactory; diff --git a/doc/nrf/protocols/matter/overview/bridge.rst b/doc/nrf/protocols/matter/overview/bridge.rst index 6abe6e51712..a50bb4e2ca0 100644 --- a/doc/nrf/protocols/matter/overview/bridge.rst +++ b/doc/nrf/protocols/matter/overview/bridge.rst @@ -43,6 +43,8 @@ Unlike native Matter nodes, the bridged device has a dedicated Bridged Device Ba Since bridged devices can be added to the bridge or removed from it at runtime, the list of endpoints exposed by the bridge can be dynamically updated. +.. _ug_matter_overview_bridge_ncs_implementation: + Implementation in the |NCS| *************************** diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index e980337ce00..c8428e054b6 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -245,6 +245,7 @@ Matter Bridge * Support for Matter Generic Switch bridged device type. * Support for On/Off Light Switch bridged device type. * Support for bindings to the On/Off Light Switch device implementation. + * Guide about extending the application by adding support for a new Matter device type, a new Bluetooth LE service or a new protocol. Samples ======= diff --git a/samples/matter/common/src/bridge/ble_connectivity_manager.cpp b/samples/matter/common/src/bridge/ble_connectivity_manager.cpp index aaeba2d383f..5ae66dee166 100644 --- a/samples/matter/common/src/bridge/ble_connectivity_manager.cpp +++ b/samples/matter/common/src/bridge/ble_connectivity_manager.cpp @@ -9,7 +9,6 @@ #include #include -#include #include diff --git a/samples/matter/common/src/bridge/bridge_manager.cpp b/samples/matter/common/src/bridge/bridge_manager.cpp index 40a15f3c6a6..cb44feffea3 100644 --- a/samples/matter/common/src/bridge/bridge_manager.cpp +++ b/samples/matter/common/src/bridge/bridge_manager.cpp @@ -429,7 +429,7 @@ void BridgeManager::HandleCommand(BridgedDeviceDataProvider &dataProvider, Clust reinterpret_cast(bindingData)); } -BridgedDeviceDataProvider *BridgeManager::GetProvider(EndpointId endpoint, MatterBridgedDevice::DeviceType &deviceType) +BridgedDeviceDataProvider *BridgeManager::GetProvider(EndpointId endpoint, uint16_t &deviceType) { uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); if (Instance().mDevicesMap.Contains(endpointIndex)) { diff --git a/samples/matter/common/src/bridge/bridge_manager.h b/samples/matter/common/src/bridge/bridge_manager.h index bc6e62dfc28..321f6dcaf92 100644 --- a/samples/matter/common/src/bridge/bridge_manager.h +++ b/samples/matter/common/src/bridge/bridge_manager.h @@ -103,7 +103,7 @@ class BridgeManager { * @param[out] deviceType a type of the bridged device * @return pointer to the data provider bridged with the device on the specified endpoint */ - BridgedDeviceDataProvider *GetProvider(chip::EndpointId endpoint, MatterBridgedDevice::DeviceType &deviceType); + BridgedDeviceDataProvider *GetProvider(chip::EndpointId endpoint, uint16_t &deviceType); static CHIP_ERROR HandleRead(uint16_t index, chip::ClusterId clusterId, const EmberAfAttributeMetadata *attributeMetadata, uint8_t *buffer, diff --git a/samples/matter/common/src/bridge/matter_bridged_device.h b/samples/matter/common/src/bridge/matter_bridged_device.h index 53ace2b2269..81fbae881b0 100644 --- a/samples/matter/common/src/bridge/matter_bridged_device.h +++ b/samples/matter/common/src/bridge/matter_bridged_device.h @@ -101,7 +101,7 @@ class MatterBridgedDevice { } chip::EndpointId GetEndpointId() const { return mEndpointId; } - virtual DeviceType GetDeviceType() const = 0; + virtual uint16_t GetDeviceType() const = 0; virtual CHIP_ERROR HandleRead(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) = 0; virtual CHIP_ERROR HandleWrite(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) = 0; diff --git a/samples/matter/common/src/bridge/util/bridge_util.h b/samples/matter/common/src/bridge/util/bridge_util.h index 3abeed37391..abc5f036ab1 100644 --- a/samples/matter/common/src/bridge/util/bridge_util.h +++ b/samples/matter/common/src/bridge/util/bridge_util.h @@ -14,10 +14,10 @@ /* DeviceFactory template container allows to instantiate a map which - binds supported MatterBridgedDevice::DeviceType types with corresponding + binds supported Matter device type identifiers (uint16_t) with corresponding creation method (e.g. constructor invocation). DeviceFactory can only be constructed by passing a user-defined initialized list with - pairs. + pairs. Then, Create() method can be used to obtain an instance of demanded device type with all passed arguments forwarded to the underlying ConcreteDeviceCreator.