An example demonstrating a simple lighting bridge and the use of dynamic endpoints. The document will describe the theory of operation and how to build and run Matter Linux Bridge Example on Raspberry Pi. This doc is tested on Ubuntu for Raspberry Pi Server 20.04 LTS (aarch64) and Ubuntu for Raspberry Pi Desktop 20.10 (aarch64)
The Bridge Example makes use of Dynamic Endpoints. Current SDK support is limited for dynamic endpoints, since endpoints are typically defined (along with the clusters and attributes they contain) in a .zap file which then generates code and static structures to define the endpoints.
To support endpoints that are not statically defined, the ZCL attribute storage mechanisms will hold additional endpoint information for NUM_DYNAMIC_ENDPOINTS
additional endpoints. These additional endpoint structures must be defined by the application and can change at runtime.
To facilitate the creation of these endpoint structures, several macros are defined:
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(attrListName)
DECLARE_DYNAMIC_ATTRIBUTE(attId, attType, attSizeBytes, attrMask)
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(clusterRevision)
These three macros are used to declare a list of attributes for use within a cluster. The declaration must begin with the DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN
macro which will define the name of the allocated attribute structure. Each attribute is then added by the DECLARE_DYNAMIC_ATTRIBUTE
macro. Finally, DECLARE_DYNAMIC_ATTRIBUTE_LIST_END
macro should be used to close the definition.
All attributes defined with these macros will be configured as ATTRIBUTE_MASK_EXTERNAL_STORAGE
in the ZCL database and therefore will rely on the application to maintain storage for the attribute. Consequently, reads or writes to these attributes must be handled within the application by the emberAfExternalAttributeWriteCallback
and emberAfExternalAttributeReadCallback
functions. See the bridge application's main.cpp
for an example of this implementation.
DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(clusterListName)
DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs, incomingCommands, outgoingCommands)
DECLARE_DYNAMIC_CLUSTER_LIST_END
DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN
macro which will define the name of the allocated cluster structure. Each cluster is then added by the DECLARE_DYNAMIC_CLUSTER
macro referencing attribute list previously defined by the DECLARE_DYNAMIC_ATTRIBUTE...
macros and the lists of incoming/outgoing commands terminated by kInvalidCommandId (or nullptr if there aren't any commands in the list). Finally, DECLARE_DYNAMIC_CLUSTER_LIST_END
macro should be used to close the definition.DECLARE_DYNAMIC_ENDPOINT(endpointName, clusterList)
DECLARE_DYNAMIC_CLUSTER...
macros.Because code generation is dependent upon the clusters and attributes defined in the .zap file (for static endpoint generation), it is necessary to include a defined endpoint within the .zap that contains all the clusters that may be used on dynamic endpoints. On the bridge example, this is done on endpoint 1, which is used as a ‘dummy’ endpoint that will be disabled at runtime. Endpoint 0 is also defined in the .zap and contains the bridge basic and configuration clusters as well as the root descriptor cluster.
The example demonstrates the use of dynamic endpoints and the concept of adding and removing endpoints at runtime. First, the example declares a bridgedLightEndpoint
data structure for a Light endpoint with OnOff
, Descriptor
, BridgedDeviceBasicInformation
, and FixedLabel
clusters.
Using this declared endpoint structure, three endpoints for three bridged lights are dynamically added at endpoint ID's 2
, 3
, and 4
, representing Light 1
, Light 2
, and Light 3
respectively.
Then, endpoint 3
is removed, simulating the deletion of Light 2
.
A fourth light, Light 4
, is then added occupying endpoint ID 5
.
Finally, Light 2
is re-added, and will occupy endpoint ID 6
.
All endpoints populate the Bridged Device Basic Information
and Fixed Label
clusters. In the Bridged Device Basic Information
cluster, the reachable
attribute is simulated. In the Fixed Label
cluster, the LabelList
attribute is simulated with the value/label pair "room"
/[light name]
.
Install tool chain
sudo apt-get install git gcc g++ python pkg-config libssl-dev libdbus-1-dev libglib2.0-dev ninja-build python3-venv python3-dev unzip
Build the example application:
cd ~/connectedhomeip/examples/bridge-app/linux git submodule update --init source third_party/connectedhomeip/scripts/activate.sh gn gen out/debug ninja -C out/debug
To delete generated executable, libraries and object files use:
cd ~/connectedhomeip/examples/bridge-app/linux rm -rf out/
Prerequisites
pi-bluetooth
via APT.Building
Follow Building section of this document.
Running
[Optional] Plug USB Bluetooth dongle
Plug USB Bluetooth dongle and find its bluetooth device number. The number after hci
is the bluetooth device number, 1
in this example.
$ hciconfig hci1: Type: Primary Bus: USB BD Address: 00:1A:7D:AA:BB:CC ACL MTU: 310:10 SCO MTU: 64:8 UP RUNNING PSCAN ISCAN RX bytes:20942 acl:1023 sco:0 events:1140 errors:0 TX bytes:16559 acl:1011 sco:0 commands:121 errors:0 hci0: Type: Primary Bus: UART BD Address: B8:27:EB:AA:BB:CC ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING PSCAN ISCAN RX bytes:8609495 acl:14 sco:0 events:217484 errors:0 TX bytes:92185 acl:20 sco:0 commands:5259 errors:0
Run Linux Bridge Example App
cd ~/connectedhomeip/examples/bridge-app/linux sudo out/debug/chip-bridge-app --ble-device [bluetooth device number] # In this example, the device we want to use is hci1 sudo out/debug/chip-bridge-app --ble-device 1
Test the device using ChipDeviceController on your laptop / workstation etc.