mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
Add client-only controller and commissioner
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#if CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
|
||||
#include <zap-generated/CHIPClusters.h>
|
||||
#include "app/CASESessionManager.h"
|
||||
#include "app/CommandSender.h"
|
||||
#include "app/InteractionModelEngine.h"
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
|
||||
|
||||
@@ -242,7 +243,8 @@ esp_err_t send_command(void *ctx, peer_device_t *remote_device, const CommandPat
|
||||
ESP_LOGE(TAG, "No memory for command sender");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
if (command_sender->PrepareCommand(command_path, /* aStartDataStruct */ false) != CHIP_NO_ERROR) {
|
||||
chip::app::CommandSender::PrepareCommandParameters prepare_command_params;
|
||||
if (command_sender->PrepareCommand(command_path, prepare_command_params) != CHIP_NO_ERROR) {
|
||||
ESP_LOGE(TAG, "Failed to prepare command");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -256,7 +258,8 @@ esp_err_t send_command(void *ctx, peer_device_t *remote_device, const CommandPat
|
||||
ESP_LOGE(TAG, "Failed to convert json string to TLV");
|
||||
return err;
|
||||
}
|
||||
if (command_sender->FinishCommand(timed_invoke_timeout_ms) != CHIP_NO_ERROR) {
|
||||
chip::app::CommandSender::FinishCommandParameters finish_command_params(timed_invoke_timeout_ms);
|
||||
if (command_sender->FinishCommand(finish_command_params) != CHIP_NO_ERROR) {
|
||||
ESP_LOGE(TAG, "Failed to finish command");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -284,7 +287,8 @@ esp_err_t send_group_command(const uint8_t fabric_index, const CommandPathParams
|
||||
ESP_LOGE(TAG, "No memory for command sender");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
if (command_sender->PrepareCommand(command_path, /* aStartDataStruct */ false) != CHIP_NO_ERROR) {
|
||||
chip::app::CommandSender::PrepareCommandParameters prepare_command_params;
|
||||
if (command_sender->PrepareCommand(command_path, prepare_command_params) != CHIP_NO_ERROR) {
|
||||
ESP_LOGE(TAG, "Failed to prepare command");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -298,7 +302,8 @@ esp_err_t send_group_command(const uint8_t fabric_index, const CommandPathParams
|
||||
ESP_LOGE(TAG, "Failed to convert json string to TLV");
|
||||
return err;
|
||||
}
|
||||
if (command_sender->FinishCommand(chip::NullOptional) != CHIP_NO_ERROR) {
|
||||
chip::app::CommandSender::FinishCommandParameters finish_command_params;
|
||||
if (command_sender->FinishCommand(finish_command_params) != CHIP_NO_ERROR) {
|
||||
ESP_LOGE(TAG, "Failed to finish command");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -1037,6 +1037,7 @@ static esp_err_t chip_init(event_callback_t callback, intptr_t callback_arg)
|
||||
// Wait for the matter stack to be initialized
|
||||
xTaskNotifyWait(0, 0, NULL, portMAX_DELAY);
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -1068,11 +1069,14 @@ esp_err_t start(event_callback_t callback, intptr_t callback_arg)
|
||||
return err;
|
||||
}
|
||||
esp_matter_started = true;
|
||||
#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
// If Matter server is not enabled. we will never use minimum unused endpoint id.
|
||||
err = node::read_min_unused_endpoint_id();
|
||||
// If the min_unused_endpoint_id is not found, we will write the current min_unused_endpoint_id in nvs.
|
||||
if (err == ESP_ERR_NVS_NOT_FOUND) {
|
||||
err = node::store_min_unused_endpoint_id();
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,18 +3,29 @@ set(include_dirs_list )
|
||||
set(exclude_srcs_list )
|
||||
|
||||
if (CONFIG_ESP_MATTER_CONTROLLER_ENABLE)
|
||||
list(APPEND src_dirs_list "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/logger/zap-generated")
|
||||
list(APPEND include_dirs_list "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/logger")
|
||||
list(APPEND src_dirs_list "${CMAKE_CURRENT_SOURCE_DIR}/core"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/commands"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/logger/zap-generated")
|
||||
list(APPEND include_dirs_list "${CMAKE_CURRENT_SOURCE_DIR}/core"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/commands"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/logger")
|
||||
|
||||
if (CONFIG_ESP_MATTER_CONTROLLER_CUSTOM_CLUSTER_ENABLE)
|
||||
list(APPEND src_dirs_list "${CMAKE_CURRENT_SOURCE_DIR}/controller_custom_cluster")
|
||||
list(APPEND include_dirs_list "${CMAKE_CURRENT_SOURCE_DIR}/controller_custom_cluster")
|
||||
endif()
|
||||
if (NOT CONFIG_ESP_MATTER_COMMISSIONER_ENABLE)
|
||||
list(APPEND exclude_srcs_list "${CMAKE_CURRENT_SOURCE_DIR}/esp_matter_commissioner.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/esp_matter_controller_pairing_command.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/esp_matter_attestation_trust_store.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/esp_matter_controller_group_settings.cpp")
|
||||
|
||||
if (CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER)
|
||||
list(APPEND exclude_srcs_list "${CMAKE_CURRENT_SOURCE_DIR}/core/esp_matter_controller_client.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/core/esp_matter_controller_credentials_issuer.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/core/esp_matter_controller_group_settings.cpp")
|
||||
endif()
|
||||
|
||||
if (CONFIG_ESP_MATTER_COMMISSIONER_ENABLE)
|
||||
list(APPEND src_dirs_list "${CMAKE_CURRENT_SOURCE_DIR}/attestation_store")
|
||||
list(APPEND include_dirs_list "${CMAKE_CURRENT_SOURCE_DIR}/attestation_store")
|
||||
else()
|
||||
list(APPEND exclude_srcs_list "${CMAKE_CURRENT_SOURCE_DIR}/commands/esp_matter_controller_pairing_command.cpp")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -6,20 +6,20 @@ menu "ESP Matter Controller"
|
||||
help
|
||||
Enable the controller.
|
||||
|
||||
config ESP_MATTER_CONTROLLER_VENDOR_ID
|
||||
int "Matter Controller Vendor ID"
|
||||
depends on ESP_MATTER_CONTROLLER_ENABLE && !ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
default 4891
|
||||
help
|
||||
Vendor ID for the controller
|
||||
|
||||
config ESP_MATTER_COMMISSIONER_ENABLE
|
||||
bool "Enable matter commissioner"
|
||||
depends on ESP_MATTER_CONTROLLER_ENABLE
|
||||
depends on ESP_MATTER_CONTROLLER_ENABLE && !ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
default y
|
||||
help
|
||||
Enable the matter commissioner in the ESP Matter controller.
|
||||
|
||||
config ESP_MATTER_COMMISSIONER_MAX_ACTIVE_DEVICES
|
||||
int "Max active device"
|
||||
depends on ESP_MATTER_COMMISSIONER_ENABLE
|
||||
default 5
|
||||
help
|
||||
Maximum number of active device the commissioner supports.
|
||||
|
||||
config ESP_MATTER_CONTROLLER_JSON_STRING_BUFFER_LEN
|
||||
int "Max JSON string buffer length"
|
||||
depends on ESP_MATTER_CONTROLLER_ENABLE
|
||||
@@ -30,8 +30,8 @@ menu "ESP Matter Controller"
|
||||
|
||||
config ESP_MATTER_CONTROLLER_CUSTOM_CLUSTER_ENABLE
|
||||
bool "Enable controller custom cluster"
|
||||
depends on ESP_MATTER_CONTROLLER_ENABLE && !ESP_MATTER_COMMISSIONER_ENABLE
|
||||
default y
|
||||
depends on ESP_MATTER_CONTROLLER_ENABLE && ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
default n
|
||||
help
|
||||
Enable the custom cluster of matter controller in the ESP Matter controller for Rainmaker Fabric suppport.
|
||||
|
||||
@@ -52,6 +52,30 @@ menu "ESP Matter Controller"
|
||||
help
|
||||
Read the PAA root certificates from the spiffs partition
|
||||
|
||||
config CUSTOM_ATTESTATION_TRUST_STORE
|
||||
bool "Attestation Trust Store - Custom"
|
||||
help
|
||||
Use the custom Attestation Trust Store
|
||||
|
||||
endchoice
|
||||
|
||||
choice ESP_MATTER_COMMISSIONER_OPERATIONAL_CREDS_ISSUER
|
||||
prompt "Operational Credentials Issuer"
|
||||
depends on !ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
default TEST_OPERATIONAL_CREDS_ISSUER
|
||||
help
|
||||
This option determines how the commissioner generates the NOC chains for the end-devices and itself.
|
||||
|
||||
config TEST_OPERATIONAL_CREDS_ISSUER
|
||||
bool "Operational Credentials Issuer - Test"
|
||||
help
|
||||
Use the ExampleOperationalCredentialsIssuer from Matter controller Code
|
||||
|
||||
config CUSTOM_OPERATIONAL_CREDS_ISSUER
|
||||
bool "Operational Credentials Issuer - Custom"
|
||||
help
|
||||
Use the custom OperationalCredentialsIssuer
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
+29
-18
@@ -14,17 +14,14 @@
|
||||
|
||||
#include <DataModelLogger.h>
|
||||
#include <controller/CommissioneeDeviceProxy.h>
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#include <esp_matter_commissioner.h>
|
||||
#else
|
||||
#include <app/server/Server.h>
|
||||
#endif
|
||||
#include <esp_check.h>
|
||||
#include <esp_matter_controller_client.h>
|
||||
#include <esp_matter_controller_cluster_command.h>
|
||||
#include <esp_matter_controller_utils.h>
|
||||
#include <esp_matter_mem.h>
|
||||
#include <json_parser.h>
|
||||
|
||||
#include <app/server/Server.h>
|
||||
#include <crypto/CHIPCryptoPAL.h>
|
||||
#include <setup_payload/ManualSetupPayloadGenerator.h>
|
||||
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
|
||||
@@ -101,7 +98,8 @@ void decode_response(const ConcreteCommandPath &command_path, TLVReader *reader)
|
||||
} else if (command_path.mCommandId == ScenesManagement::Commands::StoreSceneResponse::Id) {
|
||||
decode_command_response<ScenesManagement::Commands::StoreScene::Type::ResponseType>(command_path, reader);
|
||||
} else if (command_path.mCommandId == ScenesManagement::Commands::GetSceneMembershipResponse::Id) {
|
||||
decode_command_response<ScenesManagement::Commands::GetSceneMembership::Type::ResponseType>(command_path, reader);
|
||||
decode_command_response<ScenesManagement::Commands::GetSceneMembership::Type::ResponseType>(command_path,
|
||||
reader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,11 +207,15 @@ esp_err_t cluster_command::dispatch_group_command(void *context)
|
||||
esp_err_t err = ESP_OK;
|
||||
cluster_command *cmd = reinterpret_cast<cluster_command *>(context);
|
||||
uint16_t group_id = cmd->m_destination_id & 0xFFFF;
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
uint8_t fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
uint8_t fabric_index = get_fabric_index();
|
||||
#endif
|
||||
#else
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
uint8_t fabric_index = matter_controller_client::get_instance().get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
uint8_t fabric_index = matter_controller_client::get_instance().get_controller()->GetFabricIndex();
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
chip::app::CommandPathParams command_path = {cmd->m_endpoint_id, group_id, cmd->m_cluster_id, cmd->m_command_id,
|
||||
chip::app::CommandPathFlags::kGroupIdValid};
|
||||
err = custom::command::send_group_command(fabric_index, command_path, cmd->m_command_data_field);
|
||||
@@ -226,18 +228,27 @@ esp_err_t cluster_command::send_command()
|
||||
if (is_group_command()) {
|
||||
return dispatch_group_command(reinterpret_cast<void *>(this));
|
||||
}
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
chip::Server &server = chip::Server::GetInstance();
|
||||
server.GetCASESessionManager()->FindOrEstablishSession(ScopedNodeId(m_destination_id, get_fabric_index()),
|
||||
&on_device_connected_cb, &on_device_connection_failure_cb);
|
||||
return ESP_OK;
|
||||
#else
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
if (CHIP_NO_ERROR ==
|
||||
commissioner::get_device_commissioner()->GetConnectedDevice(m_destination_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
controller_instance.get_commissioner()->GetConnectedDevice(m_destination_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#else
|
||||
chip::Server *server = &(chip::Server::GetInstance());
|
||||
server->GetCASESessionManager()->FindOrEstablishSession(ScopedNodeId(m_destination_id, get_fabric_index()),
|
||||
&on_device_connected_cb, &on_device_connection_failure_cb);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
if (CHIP_NO_ERROR ==
|
||||
controller_instance.get_controller()->GetConnectedDevice(m_destination_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
chip::Platform::Delete(this);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
+18
-2
@@ -34,6 +34,7 @@ using esp_matter::cluster::custom::command::custom_command_callback;
|
||||
constexpr char k_empty_command_data_field[] = "{}";
|
||||
constexpr size_t k_command_data_field_buffer_size = CONFIG_ESP_MATTER_CONTROLLER_JSON_STRING_BUFFER_LEN;
|
||||
|
||||
/** Cluster command class to send an invoke interaction command to a server **/
|
||||
class cluster_command {
|
||||
public:
|
||||
cluster_command(uint64_t destination_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t command_id,
|
||||
@@ -89,8 +90,23 @@ private:
|
||||
custom_command_callback::on_error_callback_t on_error_cb;
|
||||
};
|
||||
|
||||
esp_err_t send_invoke_cluster_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t command_id,
|
||||
const char *command_data_field);
|
||||
/** Send cluster invoke command
|
||||
*
|
||||
* @note When the destination_id is a Matter GroupId, the endpoint_id parameter will be ignored.
|
||||
* @note When the command has no data field, command_data_field can be NULL.
|
||||
*
|
||||
* @param[in] destination_id NodeId or GroupId
|
||||
* @param[in] endpoint_id EndpointId
|
||||
* @param[in] cluster_id ClusterId
|
||||
* @param[in] command_id CommandId
|
||||
* @param[in] command_data_field Command data string with JSON format
|
||||
* (https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#cluster-commands)
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_invoke_cluster_command(uint64_t destination_id, uint16_t endpoint_id, uint32_t cluster_id,
|
||||
uint32_t command_id, const char *command_data_field);
|
||||
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
+18
-32
@@ -12,20 +12,18 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <esp_matter_commissioner.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_matter_controller_client.h>
|
||||
#include <esp_matter_controller_pairing_command.h>
|
||||
|
||||
static const char *TAG = "pairing_command";
|
||||
|
||||
using namespace esp_matter::commissioner;
|
||||
using namespace chip;
|
||||
using namespace chip::Controller;
|
||||
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
|
||||
pairing_command pairing_command::instance;
|
||||
|
||||
void pairing_command::OnStatusUpdate(DevicePairingDelegate::Status status)
|
||||
{
|
||||
switch (status) {
|
||||
@@ -60,14 +58,11 @@ void pairing_command::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err)
|
||||
{
|
||||
if (err == CHIP_NO_ERROR) {
|
||||
ESP_LOGI(TAG, "Device commissioning completed with success - getting OperationalDeviceProxy");
|
||||
esp_matter::commissioner::get_device_commissioner()->GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback,
|
||||
&mOnDeviceConnectionFailureCallback);
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
controller_instance.get_commissioner()->GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback,
|
||||
&mOnDeviceConnectionFailureCallback);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Device commissioning Failure: Matter%s", ErrorStr(err));
|
||||
CommissionerDiscoveryController *cdc = esp_matter::commissioner::get_discovery_controller();
|
||||
if (cdc != nullptr) {
|
||||
cdc->CommissioningFailed(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,24 +70,11 @@ void pairing_command::OnDeviceConnectedFn(void *context, ExchangeManager &exchan
|
||||
const SessionHandle &sessionHandle)
|
||||
{
|
||||
ESP_LOGI(TAG, "OnDeviceConnectedFn");
|
||||
CommissionerDiscoveryController *cdc = esp_matter::commissioner::get_discovery_controller();
|
||||
|
||||
if (cdc != nullptr) {
|
||||
uint16_t vendorId = get_auto_commissioner()->GetCommissioningParameters().GetRemoteVendorId().Value();
|
||||
uint16_t productId = get_auto_commissioner()->GetCommissioningParameters().GetRemoteProductId().Value();
|
||||
ESP_LOGI(TAG, " ----- AutoCommissioner -- Commissionee vendorId=0x%04X productId=0x%04X", vendorId, productId);
|
||||
|
||||
cdc->CommissioningSucceeded(vendorId, productId, get_instance().m_remote_node_id, exchangeMgr, sessionHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void pairing_command::OnDeviceConnectionFailureFn(void *context, const ScopedNodeId &peerId, CHIP_ERROR err)
|
||||
{
|
||||
ESP_LOGI(TAG, "OnDeviceConnectionFailureFn - attempt to get OperationalDeviceProxy failed");
|
||||
CommissionerDiscoveryController *cdc = esp_matter::commissioner::get_discovery_controller();
|
||||
if (cdc != nullptr) {
|
||||
cdc->CommissioningFailed(err);
|
||||
}
|
||||
}
|
||||
|
||||
CommissioningParameters pairing_command::get_commissioning_params()
|
||||
@@ -111,6 +93,7 @@ CommissioningParameters pairing_command::get_commissioning_params()
|
||||
|
||||
void pairing_command::OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData &nodeData)
|
||||
{
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
// Ignore nodes with closed comissioning window
|
||||
VerifyOrReturn(nodeData.commissionData.commissioningMode != 0);
|
||||
const uint16_t port = nodeData.resolutionData.port;
|
||||
@@ -119,7 +102,7 @@ void pairing_command::OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData &
|
||||
ESP_LOGI(TAG, "Discovered Device: %s:%u", buf, port);
|
||||
|
||||
// Stop Mdns discovery. TODO: Check whether it is a right method
|
||||
get_device_commissioner()->RegisterDeviceDiscoveryDelegate(nullptr);
|
||||
controller_instance.get_commissioner()->RegisterDeviceDiscoveryDelegate(nullptr);
|
||||
|
||||
Inet::InterfaceId interfaceId = nodeData.resolutionData.ipAddress[0].IsIPv6LinkLocal()
|
||||
? nodeData.resolutionData.interfaceId
|
||||
@@ -127,18 +110,19 @@ void pairing_command::OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData &
|
||||
PeerAddress peerAddress = PeerAddress::UDP(nodeData.resolutionData.ipAddress[0], port, interfaceId);
|
||||
RendezvousParameters params = RendezvousParameters().SetSetupPINCode(m_setup_pincode).SetPeerAddress(peerAddress);
|
||||
CommissioningParameters commissioning_params = get_commissioning_params();
|
||||
get_device_commissioner()->PairDevice(m_remote_node_id, params, commissioning_params);
|
||||
controller_instance.get_commissioner()->PairDevice(m_remote_node_id, params, commissioning_params);
|
||||
}
|
||||
|
||||
esp_err_t pairing_on_network(NodeId node_id, uint32_t pincode)
|
||||
{
|
||||
Dnssd::DiscoveryFilter filter(chip::Dnssd::DiscoveryFilterType::kNone);
|
||||
get_device_commissioner()->RegisterDeviceDiscoveryDelegate(&pairing_command::get_instance());
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
controller_instance.get_commissioner()->RegisterDeviceDiscoveryDelegate(&pairing_command::get_instance());
|
||||
pairing_command::get_instance().m_pairing_mode = PAIRING_MODE_ONNETWORK;
|
||||
pairing_command::get_instance().m_setup_pincode = pincode;
|
||||
pairing_command::get_instance().m_remote_node_id = node_id;
|
||||
pairing_command::get_instance().m_pairing_network_type = NETWORK_TYPE_NONE;
|
||||
if (CHIP_NO_ERROR != get_device_commissioner()->DiscoverCommissionableNodes(filter)) {
|
||||
if (CHIP_NO_ERROR != controller_instance.get_commissioner()->DiscoverCommissionableNodes(filter)) {
|
||||
ESP_LOGE(TAG, "Failed to discover commissionable nodes");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -155,19 +139,21 @@ esp_err_t pairing_ble_wifi(NodeId node_id, uint32_t pincode, uint16_t disc, cons
|
||||
chip::ByteSpan pwdSpan(reinterpret_cast<const uint8_t *>(pwd), strlen(pwd));
|
||||
CommissioningParameters commissioning_params =
|
||||
CommissioningParameters().SetWiFiCredentials(Controller::WiFiCredentials(nameSpan, pwdSpan));
|
||||
get_device_commissioner()->PairDevice(node_id, params, commissioning_params);
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
controller_instance.get_commissioner()->PairDevice(node_id, params, commissioning_params);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pairing_ble_thread(NodeId node_id, uint32_t pincode, uint16_t disc, uint8_t *dataset_tlvs, uint8_t dataset_len)
|
||||
esp_err_t pairing_ble_thread(NodeId node_id, uint32_t pincode, uint16_t disc, uint8_t *dataset_tlvs,
|
||||
uint8_t dataset_len)
|
||||
{
|
||||
RendezvousParameters params = RendezvousParameters().SetSetupPINCode(pincode).SetDiscriminator(disc).SetPeerAddress(
|
||||
chip::Transport::PeerAddress::BLE());
|
||||
|
||||
chip::ByteSpan dataset_span(dataset_tlvs, dataset_len);
|
||||
CommissioningParameters commissioning_params =
|
||||
CommissioningParameters().SetThreadOperationalDataset(dataset_span);
|
||||
get_device_commissioner()->PairDevice(node_id, params, commissioning_params);
|
||||
CommissioningParameters commissioning_params = CommissioningParameters().SetThreadOperationalDataset(dataset_span);
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
controller_instance.get_commissioner()->PairDevice(node_id, params, commissioning_params);
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
+47
-10
@@ -42,15 +42,10 @@ typedef enum pairing_mode {
|
||||
PAIRING_MODE_ONNETWORK,
|
||||
} pairing_mode_t;
|
||||
|
||||
/** Pairing command class to finish commissioning with Matter end-devices **/
|
||||
class pairing_command : public chip::Controller::DevicePairingDelegate,
|
||||
public chip::Controller::DeviceDiscoveryDelegate {
|
||||
public:
|
||||
pairing_command()
|
||||
: mOnDeviceConnectedCallback(OnDeviceConnectedFn, this)
|
||||
, mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
|
||||
{
|
||||
}
|
||||
|
||||
/****************** DevicePairingDelegate Interface *****************/
|
||||
void OnStatusUpdate(DevicePairingDelegate::Status status) override;
|
||||
void OnPairingComplete(CHIP_ERROR error) override;
|
||||
@@ -60,7 +55,11 @@ public:
|
||||
/****************** DeviceDiscoveryDelegate Interface ***************/
|
||||
void OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData &nodeData) override;
|
||||
|
||||
static pairing_command &get_instance() { return instance; }
|
||||
static pairing_command &get_instance()
|
||||
{
|
||||
static pairing_command s_instance;
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
NodeId m_remote_node_id;
|
||||
uint32_t m_setup_pincode;
|
||||
@@ -69,19 +68,57 @@ public:
|
||||
pairing_mode_t m_pairing_mode;
|
||||
|
||||
private:
|
||||
static pairing_command instance;
|
||||
pairing_command()
|
||||
: mOnDeviceConnectedCallback(OnDeviceConnectedFn, this)
|
||||
, mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
|
||||
{
|
||||
}
|
||||
CommissioningParameters get_commissioning_params();
|
||||
|
||||
static void OnDeviceConnectedFn(void *context, ExchangeManager &exchangeMgr, const SessionHandle &sessionHandle);
|
||||
static void OnDeviceConnectionFailureFn(void *context, const ScopedNodeId &peerId, CHIP_ERROR error);
|
||||
|
||||
CommissioningParameters get_commissioning_params();
|
||||
|
||||
chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
|
||||
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pairing a Matter end-device on the same IP network
|
||||
*
|
||||
* @param[in] node_id NodeId assigned to the Matter end-device.
|
||||
* @param[in] pincode Setup PIN code of the Matter end-device.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t pairing_on_network(NodeId node_id, uint32_t pincode);
|
||||
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
/**
|
||||
* Pairing a Matter over Wi-Fi end-device with BLE
|
||||
*
|
||||
* @param[in] node_id NodeId assigned to the Matter end-device.
|
||||
* @param[in] pincode Setup PIN code of the Matter end-device.
|
||||
* @param[in] disc Discriminator of the Matter end-device.
|
||||
* @param[in] ssid SSID of the Wi-Fi AP.
|
||||
* @param[in] pwd Password of the Wi-Fi AP.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t pairing_ble_wifi(NodeId node_id, uint32_t pincode, uint16_t disc, const char *ssid, const char *pwd);
|
||||
|
||||
/**
|
||||
* Pairing a Matter over Thread end-device with BLE
|
||||
*
|
||||
* @param[in] node_id NodeId assigned to the Matter end-device.
|
||||
* @param[in] pincode Setup PIN code of the Matter end-device.
|
||||
* @param[in] disc Discriminator of the Matter end-device.
|
||||
* @param[in] dataset_tlvs Dataset TLV string of the Thread network.
|
||||
* @param[in] dataset_len Length of the dataset TLV string.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t pairing_ble_thread(NodeId node_id, uint32_t pincode, uint16_t disc, uint8_t *dataset_tlvs,
|
||||
uint8_t dataset_len);
|
||||
#endif
|
||||
+23
-17
@@ -12,13 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <app/server/Server.h>
|
||||
#include <controller/CommissioneeDeviceProxy.h>
|
||||
#include <esp_log.h>
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#include <esp_matter_commissioner.h>
|
||||
#else
|
||||
#include <app/server/Server.h>
|
||||
#endif
|
||||
#include <esp_matter_controller_client.h>
|
||||
#include <esp_matter_controller_read_command.h>
|
||||
|
||||
#include "DataModelLogger.h"
|
||||
@@ -76,18 +73,27 @@ void read_command::on_device_connection_failure_fcn(void *context, const ScopedN
|
||||
|
||||
esp_err_t read_command::send_command()
|
||||
{
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
chip::Server &server = chip::Server::GetInstance();
|
||||
server.GetCASESessionManager()->FindOrEstablishSession(ScopedNodeId(m_node_id, get_fabric_index()),
|
||||
&on_device_connected_cb, &on_device_connection_failure_cb);
|
||||
return ESP_OK;
|
||||
#else
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
if (CHIP_NO_ERROR ==
|
||||
commissioner::get_device_commissioner()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
controller_instance.get_commissioner()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#else
|
||||
chip::Server *server = &(chip::Server::GetInstance());
|
||||
server->GetCASESessionManager()->FindOrEstablishSession(ScopedNodeId(m_node_id, get_fabric_index()),
|
||||
&on_device_connected_cb, &on_device_connection_failure_cb);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
if (CHIP_NO_ERROR ==
|
||||
controller_instance.get_controller()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
|
||||
chip::Platform::Delete(this);
|
||||
return ESP_FAIL;
|
||||
@@ -188,8 +194,8 @@ esp_err_t send_read_attr_command(uint64_t node_id, ScopedMemoryBufferWithSize<ui
|
||||
attr_paths[i] = AttributePathParams(endpoint_ids[i], cluster_ids[i], attribute_ids[i]);
|
||||
}
|
||||
|
||||
read_command *cmd =
|
||||
chip::Platform::New<read_command>(node_id, std::move(attr_paths), std::move(event_paths), nullptr, nullptr, nullptr);
|
||||
read_command *cmd = chip::Platform::New<read_command>(node_id, std::move(attr_paths), std::move(event_paths),
|
||||
nullptr, nullptr, nullptr);
|
||||
if (!cmd) {
|
||||
ESP_LOGE(TAG, "Failed to alloc memory for read_command");
|
||||
return ESP_ERR_NO_MEM;
|
||||
@@ -219,8 +225,8 @@ esp_err_t send_read_event_command(uint64_t node_id, ScopedMemoryBufferWithSize<u
|
||||
event_paths[i] = EventPathParams(endpoint_ids[i], cluster_ids[i], event_ids[i]);
|
||||
}
|
||||
|
||||
read_command *cmd =
|
||||
chip::Platform::New<read_command>(node_id, std::move(attr_paths), std::move(event_paths), nullptr, nullptr, nullptr);
|
||||
read_command *cmd = chip::Platform::New<read_command>(node_id, std::move(attr_paths), std::move(event_paths),
|
||||
nullptr, nullptr, nullptr);
|
||||
if (!cmd) {
|
||||
ESP_LOGE(TAG, "Failed to alloc memory for read_command");
|
||||
return ESP_ERR_NO_MEM;
|
||||
+58
-2
@@ -38,8 +38,10 @@ typedef enum {
|
||||
READ_EVENT,
|
||||
} read_command_type_t;
|
||||
|
||||
/** Read command class to send a read interaction command to a server **/
|
||||
class read_command : public ReadClient::Callback {
|
||||
public:
|
||||
/** Constructor for command with multiple paths**/
|
||||
read_command(uint64_t node_id, ScopedMemoryBufferWithSize<AttributePathParams> &&attr_paths,
|
||||
ScopedMemoryBufferWithSize<EventPathParams> &&event_paths, attribute_report_cb_t attribute_cb,
|
||||
read_done_cb_t read_cb_done, event_report_cb_t event_cb)
|
||||
@@ -54,7 +56,10 @@ public:
|
||||
, event_data_cb(event_cb)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor for command with single path.
|
||||
* @note 0xFFFF could be used as wildcard EndpointId
|
||||
* @note 0xFFFFFFFF could be used as wildcard ClusterId/AttributeId/EventId
|
||||
*/
|
||||
read_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_or_event_id,
|
||||
read_command_type_t command_type, attribute_report_cb_t attribute_cb, read_done_cb_t read_cb_done,
|
||||
event_report_cb_t event_cb)
|
||||
@@ -113,19 +118,70 @@ private:
|
||||
attribute_report_cb_t attribute_data_cb;
|
||||
read_done_cb_t read_done_cb;
|
||||
event_report_cb_t event_data_cb;
|
||||
|
||||
};
|
||||
|
||||
/** Send read command with multiple attribute paths
|
||||
*
|
||||
* @note The three arrays should has the same size and the order of the three arrays should be the same as
|
||||
* the attribute paths.
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_ids EndpointId array of the multiple attribute paths
|
||||
* @param[in] cluster_ids ClusterId array of the multiple attribute paths
|
||||
* @param[in] attribute_ids AttributeId array of the multiple attribute paths
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_read_attr_command(uint64_t node_id, ScopedMemoryBufferWithSize<uint16_t> &endpoint_ids,
|
||||
ScopedMemoryBufferWithSize<uint32_t> &cluster_ids,
|
||||
ScopedMemoryBufferWithSize<uint32_t> &attribute_ids);
|
||||
|
||||
/** Send read command with multiple event paths
|
||||
*
|
||||
* @note The three arrays should has the same size and the order of the three arrays should be the same as
|
||||
* the event paths.
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_ids EndpointId array of the multiple event paths
|
||||
* @param[in] cluster_ids ClusterId array of the multiple event paths
|
||||
* @param[in] event_ids EventId array of the multiple event paths
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_read_event_command(uint64_t node_id, ScopedMemoryBufferWithSize<uint16_t> &endpoint_ids,
|
||||
ScopedMemoryBufferWithSize<uint32_t> &cluster_ids,
|
||||
ScopedMemoryBufferWithSize<uint32_t> &event_ids);
|
||||
|
||||
/** Send read command with single attribute path
|
||||
*
|
||||
* @note 0xFFFF could be used as wildcard EndpointId
|
||||
* @note 0xFFFFFFFF could be used as wildcard ClusterId/AttributeId/EventId
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_id EndpointId
|
||||
* @param[in] cluster_id ClusterId
|
||||
* @param[in] attribute_id AttributeId
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_read_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id);
|
||||
|
||||
/** Send read command with single event path
|
||||
*
|
||||
* @note 0xFFFF could be used as wildcard EndpointId
|
||||
* @note 0xFFFFFFFF could be used as wildcard ClusterId/AttributeId/EventId
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_id EndpointId
|
||||
* @param[in] cluster_id ClusterId
|
||||
* @param[in] event_id EventId
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_read_event_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t event_id);
|
||||
|
||||
} // namespace controller
|
||||
+21
-14
@@ -12,13 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <app/server/Server.h>
|
||||
#include <controller/CommissioneeDeviceProxy.h>
|
||||
#include <esp_log.h>
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#include <esp_matter_commissioner.h>
|
||||
#else
|
||||
#include <app/server/Server.h>
|
||||
#endif
|
||||
#include <esp_matter_controller_client.h>
|
||||
#include <esp_matter_controller_subscribe_command.h>
|
||||
|
||||
#include "DataModelLogger.h"
|
||||
@@ -92,18 +89,27 @@ void subscribe_command::on_device_connection_failure_fcn(void *context, const Sc
|
||||
|
||||
esp_err_t subscribe_command::send_command()
|
||||
{
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
if (CHIP_NO_ERROR ==
|
||||
commissioner::get_device_commissioner()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#else
|
||||
#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
chip::Server *server = &(chip::Server::GetInstance());
|
||||
server->GetCASESessionManager()->FindOrEstablishSession(ScopedNodeId(m_node_id, get_fabric_index()),
|
||||
&on_device_connected_cb, &on_device_connection_failure_cb);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
#else
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
if (CHIP_NO_ERROR ==
|
||||
controller_instance.get_commissioner()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#else
|
||||
if (CHIP_NO_ERROR ==
|
||||
controller_instance.get_controller()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
chip::Platform::Delete(this);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -304,7 +310,8 @@ esp_err_t send_shutdown_subscription(uint64_t node_id, uint32_t subscription_id)
|
||||
if (CHIP_NO_ERROR !=
|
||||
InteractionModelEngine::GetInstance()->ShutdownSubscription(
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
ScopedNodeId(node_id, commissioner::get_device_commissioner()->GetFabricIndex()), subscription_id)) {
|
||||
ScopedNodeId(node_id, matter_controller_client::get_instance().get_commissioner()->GetFabricIndex()),
|
||||
subscription_id)) {
|
||||
#else
|
||||
ScopedNodeId(node_id, /* fabric index */ 1), subscription_id)) {
|
||||
#endif
|
||||
+70
@@ -38,8 +38,10 @@ typedef enum {
|
||||
SUBSCRIBE_EVENT,
|
||||
} subscribe_command_type_t;
|
||||
|
||||
/** Subscribe command class to send a subscribe interaction command to a server **/
|
||||
class subscribe_command : public ReadClient::Callback {
|
||||
public:
|
||||
/** Constructor for command with multiple paths**/
|
||||
subscribe_command(uint64_t node_id, ScopedMemoryBufferWithSize<AttributePathParams> &&attr_paths,
|
||||
ScopedMemoryBufferWithSize<EventPathParams> &&event_paths, uint16_t min_interval,
|
||||
uint16_t max_interval, bool auto_resubscribe = true, attribute_report_cb_t attribute_cb = nullptr,
|
||||
@@ -61,6 +63,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor for command with single path.
|
||||
* @note 0xFFFF could be used as wildcard EndpointId
|
||||
* @note 0xFFFFFFFF could be used as wildcard ClusterId/AttributeId/EventId
|
||||
*/
|
||||
subscribe_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_or_event_id,
|
||||
subscribe_command_type_t command_type, uint16_t min_interval, uint16_t max_interval,
|
||||
bool auto_resubscribe = true, attribute_report_cb_t attribute_cb = nullptr,
|
||||
@@ -135,20 +141,84 @@ private:
|
||||
subscribe_failure_cb_t subscribe_failure_cb;
|
||||
};
|
||||
|
||||
/** Send subscribe command with multiple attribute paths
|
||||
*
|
||||
* @note The three arrays should has the same size and the order of the three arrays should be the same as
|
||||
* the attribute paths.
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_ids EndpointId array of the multiple attribute paths
|
||||
* @param[in] cluster_ids ClusterId array of the multiple attribute paths
|
||||
* @param[in] attribute_ids AttributeId array of the multiple attribute paths
|
||||
* @param[in] min_interval Minimum interval of the subscription
|
||||
* @param[in] max_interval Maximum interval of the subscription
|
||||
* @param[in] auto_resubscribe Auto re-subscribe flag
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_subscribe_attr_command(uint64_t node_id, ScopedMemoryBufferWithSize<uint16_t> &endpoint_ids,
|
||||
ScopedMemoryBufferWithSize<uint32_t> &cluster_ids,
|
||||
ScopedMemoryBufferWithSize<uint32_t> &attribute_ids, uint16_t min_interval,
|
||||
uint16_t max_interval, bool auto_resubscribe = true);
|
||||
|
||||
/** Send subscribe command with multiple event paths
|
||||
*
|
||||
* @note The three arrays should has the same size and the order of the three arrays should be the same as
|
||||
* the event paths.
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_ids EndpointId array of the multiple event paths
|
||||
* @param[in] cluster_ids ClusterId array of the multiple event paths
|
||||
* @param[in] event_ids EventId array of the multiple event paths
|
||||
* @param[in] min_interval Minimum interval of the subscription
|
||||
* @param[in] max_interval Maximum interval of the subscription
|
||||
* @param[in] auto_resubscribe Auto re-subscribe flag
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_subscribe_event_command(uint64_t node_id, ScopedMemoryBufferWithSize<uint16_t> &endpoint_ids,
|
||||
ScopedMemoryBufferWithSize<uint32_t> &cluster_ids,
|
||||
ScopedMemoryBufferWithSize<uint32_t> &event_ids, uint16_t min_interval,
|
||||
uint16_t max_interval, bool auto_resubscribe = true);
|
||||
|
||||
/** Send subscribe command with single attribute path
|
||||
*
|
||||
* @note 0xFFFF could be used as wildcard EndpointId
|
||||
* @note 0xFFFFFFFF could be used as wildcard ClusterId/AttributeId/EventId
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_id EndpointId of the attribute path
|
||||
* @param[in] cluster_id ClusterId of the attribute path
|
||||
* @param[in] attribute_id AttributeId of the attribue path
|
||||
* @param[in] min_interval Minimum interval of the subscription
|
||||
* @param[in] max_interval Maximum interval of the subscription
|
||||
* @param[in] auto_resubscribe Auto re-subscribe flag
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_subscribe_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id,
|
||||
uint32_t attribute_id, uint16_t min_interval, uint16_t max_interval,
|
||||
bool auto_resubscribe = true);
|
||||
|
||||
/** Send subscribe command with single event path
|
||||
*
|
||||
* @note 0xFFFF could be used as wildcard EndpointId
|
||||
* @note 0xFFFFFFFF could be used as wildcard ClusterId/AttributeId/EventId
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_id EndpointId of the event path
|
||||
* @param[in] cluster_id ClusterId of the event path
|
||||
* @param[in] event_id AttributeId of the event path
|
||||
* @param[in] min_interval Minimum interval of the subscription
|
||||
* @param[in] max_interval Maximum interval of the subscription
|
||||
* @param[in] auto_resubscribe Auto re-subscribe flag
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_subscribe_event_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t event_id,
|
||||
uint16_t min_interval, uint16_t max_interval, bool auto_resubscribe = true);
|
||||
|
||||
+19
-12
@@ -13,14 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <esp_check.h>
|
||||
#include <esp_matter_controller_client.h>
|
||||
#include <esp_matter_controller_utils.h>
|
||||
#include <esp_matter_controller_write_command.h>
|
||||
#include <json_to_tlv.h>
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#include <esp_matter_commissioner.h>
|
||||
#else
|
||||
|
||||
#include <app/server/Server.h>
|
||||
#endif
|
||||
|
||||
using namespace chip::app::Clusters;
|
||||
using chip::ByteSpan;
|
||||
@@ -117,18 +115,27 @@ void write_command::on_device_connection_failure_fcn(void *context, const Scoped
|
||||
|
||||
esp_err_t write_command::send_command()
|
||||
{
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
chip::Server &server = chip::Server::GetInstance();
|
||||
server.GetCASESessionManager()->FindOrEstablishSession(ScopedNodeId(m_node_id, get_fabric_index()),
|
||||
&on_device_connected_cb, &on_device_connection_failure_cb);
|
||||
return ESP_OK;
|
||||
#else
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
if (CHIP_NO_ERROR ==
|
||||
commissioner::get_device_commissioner()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
controller_instance.get_commissioner()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#else
|
||||
chip::Server *server = &(chip::Server::GetInstance());
|
||||
server->GetCASESessionManager()->FindOrEstablishSession(ScopedNodeId(m_node_id, get_fabric_index()),
|
||||
&on_device_connected_cb, &on_device_connection_failure_cb);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
if (CHIP_NO_ERROR ==
|
||||
controller_instance.get_controller()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
chip::Platform::Delete(this);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
+14
@@ -37,8 +37,10 @@ using esp_matter::client::peer_device_t;
|
||||
constexpr char *k_null_attribute_val_str = "null";
|
||||
constexpr size_t k_attr_val_str_buf_size = CONFIG_ESP_MATTER_CONTROLLER_JSON_STRING_BUFFER_LEN;
|
||||
|
||||
/** Write command class to send a write interaction command to a server **/
|
||||
class write_command : public WriteClient::Callback {
|
||||
public:
|
||||
/** Constructor for command with an attribute path**/
|
||||
write_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id,
|
||||
const char *attribute_val_str)
|
||||
: m_node_id(node_id)
|
||||
@@ -98,6 +100,18 @@ private:
|
||||
chip::Callback::Callback<chip::OnDeviceConnectionFailure> on_device_connection_failure_cb;
|
||||
};
|
||||
|
||||
/** Send write attribute command
|
||||
*
|
||||
* @param[in] node_id Remote NodeId
|
||||
* @param[in] endpoint_id EndpointId
|
||||
* @param[in] cluster_id ClusterId
|
||||
* @param[in] attribute_id AttributeId
|
||||
* @param[in] attr_val_json_str Attribute value string with JSON format
|
||||
* (https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#write-attribute-commands)
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t send_write_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id,
|
||||
const char *attr_val_json_str);
|
||||
|
||||
+1
-1
@@ -416,7 +416,7 @@ static esp_err_t fetch_rainmaker_group_id(uint16_t endpoint_id, ScopedMemoryBuff
|
||||
http_len = esp_http_client_fetch_headers(client);
|
||||
http_status_code = esp_http_client_get_status_code(client);
|
||||
if ((http_len > 0) && (http_status_code == 200)) {
|
||||
http_len = esp_http_client_read_response(client, http_payload.Get(), http_payload.AllocatedSize() - 1 );
|
||||
http_len = esp_http_client_read_response(client, http_payload.Get(), http_payload.AllocatedSize() - 1);
|
||||
http_payload[http_len] = 0;
|
||||
} else {
|
||||
http_len = esp_http_client_read_response(client, http_payload.Get(), http_payload.AllocatedSize() - 1);
|
||||
|
||||
+8
@@ -89,6 +89,7 @@ void print_device_list(matter_device_t *dev_list)
|
||||
ESP_LOGI(TAG, " {");
|
||||
ESP_LOGI(TAG, " endpoint_id: %d,", dev->endpoints[i].endpoint_id);
|
||||
ESP_LOGI(TAG, " device_type_id: 0x%lx,", dev->endpoints[i].device_type_id);
|
||||
ESP_LOGI(TAG, " device_name: %s,", dev->endpoints[i].device_name);
|
||||
ESP_LOGI(TAG, " },");
|
||||
}
|
||||
ESP_LOGI(TAG, " ]");
|
||||
@@ -195,6 +196,13 @@ static esp_err_t get_metadata(jparse_ctx_t *jctx, matter_device_t *dev)
|
||||
json_obj_leave_array(jctx);
|
||||
}
|
||||
dev->endpoint_count = 1;
|
||||
int device_name_len = ESP_MATTER_CONTROLLER_MAX_DEVICE_NAME_LEN;
|
||||
if (json_obj_get_strlen(jctx, "deviceName", &device_name_len) == 0 &&
|
||||
device_name_len < ESP_MATTER_CONTROLLER_MAX_DEVICE_NAME_LEN) {
|
||||
json_obj_get_string(jctx, "deviceName", dev->endpoints[0].device_name,
|
||||
ESP_MATTER_CONTROLLER_MAX_DEVICE_NAME_LEN);
|
||||
dev->endpoints[0].device_name[device_name_len] = 0;
|
||||
}
|
||||
}
|
||||
json_obj_get_bool(jctx, "isRainmaker", &(dev->is_rainmaker_device));
|
||||
json_obj_leave_object(jctx);
|
||||
|
||||
+2
@@ -21,10 +21,12 @@ namespace controller {
|
||||
namespace device_mgr {
|
||||
|
||||
#define ESP_MATTER_DEVICE_MAX_ENDPOINT 8
|
||||
#define ESP_MATTER_CONTROLLER_MAX_DEVICE_NAME_LEN 32
|
||||
|
||||
typedef struct endpoint_entry {
|
||||
uint16_t endpoint_id;
|
||||
uint32_t device_type_id;
|
||||
char device_name[ESP_MATTER_CONTROLLER_MAX_DEVICE_NAME_LEN];
|
||||
} endpoint_entry_t;
|
||||
|
||||
typedef struct matter_device {
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
// Copyright 2024 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <sdkconfig.h>
|
||||
|
||||
#include <esp_check.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_matter_controller_client.h>
|
||||
#include <esp_matter_controller_credentials_issuer.h>
|
||||
#include <esp_matter_controller_pairing_command.h>
|
||||
|
||||
#include <controller/CHIPDeviceControllerFactory.h>
|
||||
#include <controller/OperationalCredentialsDelegate.h>
|
||||
#include <credentials/GroupDataProvider.h>
|
||||
#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
|
||||
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
|
||||
#include <crypto/CHIPCryptoPAL.h>
|
||||
#include <lib/core/CHIPError.h>
|
||||
#include <lib/core/DataModelTypes.h>
|
||||
#include <lib/support/CHIPMem.h>
|
||||
#include <lib/support/ScopedBuffer.h>
|
||||
#include <lib/support/Span.h>
|
||||
#include <lib/support/TestGroupData.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#include <esp_matter_attestation_trust_store.h>
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
#include <platform/ESP32/BLEManagerImpl.h>
|
||||
#include <platform/internal/BLEManager.h>
|
||||
#endif
|
||||
|
||||
#define TAG "MatterController"
|
||||
|
||||
using chip::Platform::ScopedMemoryBufferWithSize;
|
||||
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
|
||||
esp_err_t matter_controller_client::init(NodeId node_id, FabricId fabric_id, uint16_t listen_port)
|
||||
{
|
||||
chip::Controller::FactoryInitParams factory_init_params;
|
||||
ESP_RETURN_ON_FALSE(m_operational_keystore.Init(&m_default_storage) == CHIP_NO_ERROR, ESP_FAIL, TAG,
|
||||
"Failed to initialize operational keystore");
|
||||
ESP_RETURN_ON_FALSE(m_operational_cert_store.Init(&m_default_storage) == CHIP_NO_ERROR, ESP_FAIL, TAG,
|
||||
"Failed to initialize operational cert store");
|
||||
// ESP_RETURN_ON_FALSE(m_icd_client_storage.Init(&m_default_storage, &m_session_key_store) == CHIP_NO_ERROR,
|
||||
// ESP_FAIL, TAG, "Failed to initialize ICD client store");
|
||||
factory_init_params.listenPort = listen_port;
|
||||
factory_init_params.fabricIndependentStorage = &m_default_storage;
|
||||
factory_init_params.operationalKeystore = &m_operational_keystore;
|
||||
factory_init_params.opCertStore = &m_operational_cert_store;
|
||||
factory_init_params.enableServerInteractions = m_operational_advertising;
|
||||
factory_init_params.sessionKeystore = &m_session_key_store;
|
||||
m_controller_node_id = node_id;
|
||||
m_controller_fabric_id = fabric_id;
|
||||
|
||||
m_group_data_provider.SetStorageDelegate(&m_default_storage);
|
||||
m_group_data_provider.SetSessionKeystore(factory_init_params.sessionKeystore);
|
||||
ESP_RETURN_ON_FALSE(m_group_data_provider.Init() == CHIP_NO_ERROR, ESP_FAIL, TAG,
|
||||
"Failed to initialize group data provider");
|
||||
factory_init_params.groupDataProvider =
|
||||
reinterpret_cast<chip::Credentials::GroupDataProvider *>(&m_group_data_provider);
|
||||
chip::Credentials::SetGroupDataProvider(factory_init_params.groupDataProvider);
|
||||
ESP_RETURN_ON_FALSE(chip::Controller::DeviceControllerFactory::GetInstance().Init(factory_init_params) ==
|
||||
CHIP_NO_ERROR,
|
||||
ESP_FAIL, TAG, "Failed to initialize DeviceControllerFactory");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_err_t matter_controller_client::setup_commissioner()
|
||||
{
|
||||
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
CHIP_ERROR err = chip::DeviceLayer::Internal::BLEMgr().Init();
|
||||
// This function will return CHIP_ERROR_INCORRECT_STATE if BLE Manager is already initialized.
|
||||
ESP_RETURN_ON_FALSE(err == CHIP_NO_ERROR || err == CHIP_ERROR_INCORRECT_STATE, ESP_FAIL, TAG,
|
||||
"Failed to initialze the BLE manager");
|
||||
ESP_RETURN_ON_FALSE(chip::DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(0, true) == CHIP_NO_ERROR, ESP_FAIL, TAG,
|
||||
"Failed to configure BLEManager");
|
||||
#endif
|
||||
chip::Controller::SetupParams commissioner_params;
|
||||
const chip::Credentials::AttestationTrustStore *trust_store = chip::Credentials::get_attestation_trust_store();
|
||||
chip::Credentials::DeviceAttestationVerifier *dac_verifier = chip::Credentials::GetDefaultDACVerifier(trust_store);
|
||||
chip::Credentials::SetDeviceAttestationVerifier(dac_verifier);
|
||||
commissioner_params.deviceAttestationVerifier = dac_verifier;
|
||||
m_credentials_issuer = get_credentials_issuer();
|
||||
ESP_RETURN_ON_FALSE(m_credentials_issuer, ESP_FAIL, TAG,
|
||||
"Please set the custom credentials_issuer before calling setup_commissioner");
|
||||
ESP_RETURN_ON_ERROR(m_credentials_issuer->initialize_credentials_issuer(m_default_storage), TAG,
|
||||
"Failed to initialize credentials_issuer");
|
||||
commissioner_params.operationalCredentialsDelegate = m_credentials_issuer->get_delegate();
|
||||
commissioner_params.controllerVendorId = chip::VendorId((uint16_t)CONFIG_ESP_MATTER_CONTROLLER_VENDOR_ID);
|
||||
|
||||
// Commissioner NOC chain
|
||||
ScopedMemoryBufferWithSize<uint8_t> noc;
|
||||
noc.Calloc(chip::Controller::kMaxCHIPDERCertLength);
|
||||
ESP_RETURN_ON_FALSE(noc.Get(), ESP_ERR_NO_MEM, TAG, "Failed allocate memory for noc");
|
||||
chip::MutableByteSpan noc_span(noc.Get(), chip::Controller::kMaxCHIPDERCertLength);
|
||||
ScopedMemoryBufferWithSize<uint8_t> icac;
|
||||
icac.Calloc(chip::Controller::kMaxCHIPDERCertLength);
|
||||
ESP_RETURN_ON_FALSE(icac.Get(), ESP_ERR_NO_MEM, TAG, "Failed allocate memory for icac");
|
||||
chip::MutableByteSpan icac_span(icac.Get(), chip::Controller::kMaxCHIPDERCertLength);
|
||||
ScopedMemoryBufferWithSize<uint8_t> rcac;
|
||||
rcac.Calloc(chip::Controller::kMaxCHIPDERCertLength);
|
||||
ESP_RETURN_ON_FALSE(rcac.Get(), ESP_ERR_NO_MEM, TAG, "Failed allocate memory for rcac");
|
||||
chip::MutableByteSpan rcac_span(rcac.Get(), chip::Controller::kMaxCHIPDERCertLength);
|
||||
// NOC Keypair
|
||||
chip::Crypto::P256Keypair ephemeral_key;
|
||||
ESP_RETURN_ON_FALSE(ephemeral_key.Initialize(chip::Crypto::ECPKeyTarget::ECDSA) == CHIP_NO_ERROR, ESP_FAIL, TAG,
|
||||
"Failed to initialize ephemeral_key pair");
|
||||
ESP_RETURN_ON_ERROR(m_credentials_issuer->generate_controller_noc_chain(m_controller_node_id,
|
||||
m_controller_fabric_id, ephemeral_key,
|
||||
rcac_span, icac_span, noc_span),
|
||||
TAG, "Failed to generate NOC chain");
|
||||
commissioner_params.operationalKeypair = &ephemeral_key;
|
||||
commissioner_params.controllerRCAC = rcac_span;
|
||||
commissioner_params.controllerICAC = icac_span;
|
||||
commissioner_params.controllerNOC = noc_span;
|
||||
commissioner_params.defaultCommissioner = &m_auto_commissioner;
|
||||
commissioner_params.enableServerInteractions = m_operational_advertising;
|
||||
auto &factory = chip::Controller::DeviceControllerFactory::GetInstance();
|
||||
ESP_RETURN_ON_FALSE(factory.SetupCommissioner(commissioner_params, m_device_commissioner) == CHIP_NO_ERROR,
|
||||
ESP_FAIL, TAG, "Failed to setup commissioner");
|
||||
|
||||
// Initialize Group Data, including IPK
|
||||
chip::FabricIndex fabric_index = m_device_commissioner.GetFabricIndex();
|
||||
ESP_RETURN_ON_FALSE(fabric_index != chip::kUndefinedFabricIndex, ESP_FAIL, TAG, "Invalid Fabric Index");
|
||||
uint8_t compressed_fabric_id[sizeof(uint64_t)] = {0};
|
||||
chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
|
||||
ESP_RETURN_ON_FALSE(m_device_commissioner.GetCompressedFabricIdBytes(compressed_fabric_id_span) == CHIP_NO_ERROR,
|
||||
ESP_FAIL, TAG, "Failed to get compressed_fabric_id");
|
||||
chip::Credentials::GroupDataProvider *group_data_provider =
|
||||
reinterpret_cast<chip::Credentials::GroupDataProvider *>(&m_group_data_provider);
|
||||
ESP_RETURN_ON_FALSE(chip::GroupTesting::InitData(group_data_provider, fabric_index, compressed_fabric_id_span) ==
|
||||
CHIP_NO_ERROR,
|
||||
ESP_FAIL, TAG, "Failed to initialize group data");
|
||||
chip::ByteSpan default_ipk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
|
||||
ESP_RETURN_ON_FALSE(chip::Credentials::SetSingleIpkEpochKey(group_data_provider, fabric_index, default_ipk,
|
||||
compressed_fabric_id_span) == CHIP_NO_ERROR,
|
||||
ESP_FAIL, TAG, "Failed to set ipk for commissioner fabric");
|
||||
// m_icd_client_storage.UpdateFabricList(fabric_index);
|
||||
m_device_commissioner.RegisterPairingDelegate(&controller::pairing_command::get_instance());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
esp_err_t matter_controller_client::setup_controller(chip::MutableByteSpan &ipk)
|
||||
{
|
||||
chip::Controller::SetupParams controller_params;
|
||||
// Controller doesn't need to verify device attestation. Set deviceAttestationVerifier to null.
|
||||
controller_params.deviceAttestationVerifier = nullptr;
|
||||
m_credentials_issuer = get_credentials_issuer();
|
||||
ESP_RETURN_ON_FALSE(m_credentials_issuer, ESP_FAIL, TAG,
|
||||
"Please set the custom credentials_issuer before calling setup_controller");
|
||||
ESP_RETURN_ON_ERROR(m_credentials_issuer->initialize_credentials_issuer(m_default_storage), TAG,
|
||||
"Failed to initialize credentials_issuer");
|
||||
controller_params.operationalCredentialsDelegate = m_credentials_issuer->get_delegate();
|
||||
controller_params.controllerVendorId = chip::VendorId((uint16_t)CONFIG_ESP_MATTER_CONTROLLER_VENDOR_ID);
|
||||
// Commissioner NOC chain
|
||||
ScopedMemoryBufferWithSize<uint8_t> noc;
|
||||
noc.Calloc(chip::Controller::kMaxCHIPDERCertLength);
|
||||
ESP_RETURN_ON_FALSE(noc.Get(), ESP_ERR_NO_MEM, TAG, "Failed allocate memory for noc");
|
||||
chip::MutableByteSpan noc_span(noc.Get(), chip::Controller::kMaxCHIPDERCertLength);
|
||||
ScopedMemoryBufferWithSize<uint8_t> icac;
|
||||
icac.Calloc(chip::Controller::kMaxCHIPDERCertLength);
|
||||
ESP_RETURN_ON_FALSE(icac.Get(), ESP_ERR_NO_MEM, TAG, "Failed allocate memory for icac");
|
||||
chip::MutableByteSpan icac_span(icac.Get(), chip::Controller::kMaxCHIPDERCertLength);
|
||||
ScopedMemoryBufferWithSize<uint8_t> rcac;
|
||||
rcac.Calloc(chip::Controller::kMaxCHIPDERCertLength);
|
||||
ESP_RETURN_ON_FALSE(rcac.Get(), ESP_ERR_NO_MEM, TAG, "Failed allocate memory for rcac");
|
||||
chip::MutableByteSpan rcac_span(rcac.Get(), chip::Controller::kMaxCHIPDERCertLength);
|
||||
chip::Crypto::P256Keypair ephemeral_key;
|
||||
ESP_RETURN_ON_ERROR(m_credentials_issuer->generate_controller_noc_chain(m_controller_node_id,
|
||||
m_controller_fabric_id, ephemeral_key,
|
||||
rcac_span, icac_span, noc_span),
|
||||
TAG, "Failed to generate NOC chain");
|
||||
// Check whether the keypair is initialized in generate_controller_noc_chain
|
||||
bool is_keypair_initialized = false;
|
||||
{
|
||||
chip::Crypto::P256ECDSASignature signature;
|
||||
is_keypair_initialized = ephemeral_key.ECDSA_sign_msg(NULL, 0, signature) != CHIP_ERROR_UNINITIALIZED;
|
||||
}
|
||||
// If not initialized, use an empty keypair.
|
||||
controller_params.operationalKeypair = is_keypair_initialized ? &ephemeral_key : nullptr;
|
||||
controller_params.controllerRCAC = rcac_span;
|
||||
controller_params.controllerICAC = icac_span;
|
||||
controller_params.controllerNOC = noc_span;
|
||||
controller_params.defaultCommissioner = nullptr;
|
||||
controller_params.enableServerInteractions = m_operational_advertising;
|
||||
controller_params.permitMultiControllerFabrics = false;
|
||||
auto &factory = chip::Controller::DeviceControllerFactory::GetInstance();
|
||||
ESP_RETURN_ON_FALSE(factory.SetupController(controller_params, m_device_controller) == CHIP_NO_ERROR, ESP_FAIL, TAG,
|
||||
"Failed to setup controller");
|
||||
|
||||
chip::FabricIndex fabric_index = m_device_controller.GetFabricIndex();
|
||||
if (fabric_index != chip::kUndefinedFabricIndex && !ipk.empty()) {
|
||||
// If we have created fabric in SetupController and IPK input is not empty, initialize Group Data with IPK.
|
||||
// Otherwise we will initialize Group Data with IPK later.
|
||||
uint8_t compressed_fabric_id[sizeof(uint64_t)] = {0};
|
||||
chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
|
||||
ESP_RETURN_ON_FALSE(m_device_controller.GetCompressedFabricIdBytes(compressed_fabric_id_span) == CHIP_NO_ERROR,
|
||||
ESP_FAIL, TAG, "Failed to get compressed_fabric_id");
|
||||
chip::Credentials::GroupDataProvider *group_data_provider =
|
||||
reinterpret_cast<chip::Credentials::GroupDataProvider *>(&m_group_data_provider);
|
||||
chip::Credentials::GroupDataProvider::KeySet keyset;
|
||||
keyset.keyset_id = chip::Credentials::GroupDataProvider::kIdentityProtectionKeySetId;
|
||||
keyset.policy = chip::app::Clusters::GroupKeyManagement::GroupKeySecurityPolicyEnum::kTrustFirst;
|
||||
keyset.num_keys_used = 1;
|
||||
keyset.epoch_keys[0].start_time = 0;
|
||||
memcpy(keyset.epoch_keys[0].key, ipk.data(), chip::Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES);
|
||||
ESP_RETURN_ON_FALSE(group_data_provider->SetKeySet(fabric_index, compressed_fabric_id_span, keyset) ==
|
||||
CHIP_NO_ERROR,
|
||||
ESP_FAIL, TAG, "Failed to set ipk for commissioner fabric");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
@@ -0,0 +1,125 @@
|
||||
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <esp_matter_controller_credentials_issuer.h>
|
||||
|
||||
#include <app/icd/client/DefaultICDClientStorage.h>
|
||||
#include <controller/AutoCommissioner.h>
|
||||
#include <controller/CHIPDeviceController.h>
|
||||
#include <controller/CommissionerDiscoveryController.h>
|
||||
#include <controller/ExampleOperationalCredentialsIssuer.h>
|
||||
#include <controller/OperationalCredentialsDelegate.h>
|
||||
#include <credentials/DeviceAttestationCredsProvider.h>
|
||||
#include <credentials/GroupDataProviderImpl.h>
|
||||
#include <credentials/PersistentStorageOpCertStore.h>
|
||||
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
|
||||
#include <crypto/PersistentStorageOperationalKeystore.h>
|
||||
#include <crypto/RawKeySessionKeystore.h>
|
||||
#include <lib/core/CHIPError.h>
|
||||
#include <lib/core/CHIPPersistentStorageDelegate.h>
|
||||
#include <lib/core/DataModelTypes.h>
|
||||
#include <lib/support/Span.h>
|
||||
#include <platform/CHIPDeviceLayer.h>
|
||||
#include <platform/KeyValueStoreManager.h>
|
||||
#include <platform/PlatformManager.h>
|
||||
#include <stdint.h>
|
||||
#include <transport/TransportMgr.h>
|
||||
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
|
||||
#ifndef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
class matter_controller_client {
|
||||
public:
|
||||
class controller_storage_delegate : public chip::PersistentStorageDelegate {
|
||||
CHIP_ERROR SyncGetKeyValue(const char *key, void *buffer, uint16_t &size) override
|
||||
{
|
||||
ESP_LOGD("MatterController", "Retrieving value from controller storage.");
|
||||
size_t bytesRead = 0;
|
||||
CHIP_ERROR err = chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size, &bytesRead);
|
||||
|
||||
if (err == CHIP_NO_ERROR) {
|
||||
ESP_LOGD("MatterController", "Retrieved value from controller storage.");
|
||||
}
|
||||
size = static_cast<uint16_t>(bytesRead);
|
||||
return err;
|
||||
}
|
||||
|
||||
CHIP_ERROR SyncSetKeyValue(const char *key, const void *value, uint16_t size) override
|
||||
{
|
||||
ESP_LOGD("MatterController", "Stored value in controller storage");
|
||||
return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
|
||||
}
|
||||
|
||||
CHIP_ERROR SyncDeleteKeyValue(const char *key) override
|
||||
{
|
||||
ESP_LOGD("MatterController", "Delete value in controller storage");
|
||||
return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(key);
|
||||
}
|
||||
};
|
||||
|
||||
using NodeId = ::chip::NodeId;
|
||||
using FabricId = ::chip::FabricId;
|
||||
using MatterDeviceCommissioner = ::chip::Controller::DeviceCommissioner;
|
||||
using MatterDeviceController = ::chip::Controller::DeviceController;
|
||||
|
||||
static constexpr uint16_t k_max_groups_per_fabric = 50;
|
||||
static constexpr uint16_t k_max_group_keys_per_fabric = 25;
|
||||
|
||||
static matter_controller_client &get_instance()
|
||||
{
|
||||
static matter_controller_client s_instance;
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
esp_err_t init(NodeId node_id, FabricId fabric_id, uint16_t listen_port);
|
||||
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_err_t setup_commissioner();
|
||||
MatterDeviceCommissioner *get_commissioner() { return &m_device_commissioner; }
|
||||
#else
|
||||
esp_err_t setup_controller(chip::MutableByteSpan &ipk);
|
||||
MatterDeviceController *get_controller() { return &m_device_controller; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
matter_controller_client() {}
|
||||
|
||||
bool m_operational_advertising = true;
|
||||
controller_storage_delegate m_default_storage;
|
||||
chip::PersistentStorageOperationalKeystore m_operational_keystore;
|
||||
chip::Credentials::PersistentStorageOpCertStore m_operational_cert_store;
|
||||
chip::Crypto::RawKeySessionKeystore m_session_key_store;
|
||||
chip::Credentials::GroupDataProviderImpl m_group_data_provider{k_max_groups_per_fabric,
|
||||
k_max_group_keys_per_fabric};
|
||||
credentials_issuer *m_credentials_issuer;
|
||||
NodeId m_controller_node_id;
|
||||
FabricId m_controller_fabric_id;
|
||||
// TODO: Enable ICD client from ESP32 platform
|
||||
// chip::app::DefaultICDClientStorage s_icd_client_storage;
|
||||
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
chip::Controller::AutoCommissioner m_auto_commissioner;
|
||||
MatterDeviceCommissioner m_device_commissioner;
|
||||
#else
|
||||
MatterDeviceController m_device_controller;
|
||||
#endif
|
||||
};
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
+82
-79
@@ -36,8 +36,8 @@
|
||||
#include <protocols/secure_channel/RendezvousParameters.h>
|
||||
|
||||
using chip::NodeId;
|
||||
using chip::Platform::ScopedMemoryBufferWithSize;
|
||||
using chip::Inet::IPAddress;
|
||||
using chip::Platform::ScopedMemoryBufferWithSize;
|
||||
using chip::Transport::PeerAddress;
|
||||
|
||||
const static char *TAG = "controller_console";
|
||||
@@ -50,7 +50,7 @@ static size_t get_array_size(const char *str)
|
||||
return 0;
|
||||
}
|
||||
size_t ret = 1;
|
||||
for (size_t i = 0; i < strlen(str); ++ i) {
|
||||
for (size_t i = 0; i < strlen(str); ++i) {
|
||||
if (str[i] == ',') {
|
||||
ret++;
|
||||
}
|
||||
@@ -133,7 +133,7 @@ static esp_err_t controller_help_handler(int argc, char **argv)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
#if defined(CONFIG_ENABLE_ESP32_BLE_CONTROLLER) && defined(CONFIG_ESP_MATTER_COMMISSIONER_ENABLE)
|
||||
static int char_to_int(char ch)
|
||||
{
|
||||
if ('A' <= ch && ch <= 'F') {
|
||||
@@ -166,7 +166,7 @@ static bool convert_hex_str_to_bytes(const char *hex_str, uint8_t *bytes, uint8_
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
#endif // defined(CONFIG_ENABLE_ESP32_BLE_CONTROLLER) && defined(CONFIG_ESP_MATTER_COMMISSIONER_ENABLE)
|
||||
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
static esp_err_t controller_pairing_handler(int argc, char **argv)
|
||||
@@ -225,7 +225,9 @@ static esp_err_t controller_pairing_handler(int argc, char **argv)
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
|
||||
#ifndef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
static esp_err_t controller_group_settings_handler(int argc, char **argv)
|
||||
{
|
||||
if (argc >= 1) {
|
||||
@@ -290,7 +292,7 @@ static esp_err_t controller_group_settings_handler(int argc, char **argv)
|
||||
ESP_LOGI(TAG, "Unbind keyset : controller group-settings unbind-keyset <group_id> <ketset_id>");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#endif
|
||||
|
||||
static esp_err_t controller_invoke_command_handler(int argc, char **argv)
|
||||
{
|
||||
@@ -416,82 +418,83 @@ static esp_err_t controller_dispatch(int argc, char **argv)
|
||||
esp_err_t controller_register_commands()
|
||||
{
|
||||
// Subcommands for root command: `controller <subcommand>`
|
||||
const static command_t controller_sub_commands[] = {
|
||||
{
|
||||
.name = "help",
|
||||
.description = "print this page",
|
||||
.handler = controller_help_handler,
|
||||
},
|
||||
const static command_t controller_sub_commands[] =
|
||||
{ {
|
||||
.name = "help",
|
||||
.description = "print this page",
|
||||
.handler = controller_help_handler,
|
||||
},
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
{
|
||||
.name = "pairing",
|
||||
.description = "Pairing a node.\n"
|
||||
"\tUsage: controller pairing onnetwork [nodeid] [pincode] OR\n"
|
||||
"\tcontroller pairing ble-wifi [nodeid] [ssid] [password] [pincode] [discriminator] OR\n"
|
||||
"\tcontroller pairing ble-thread [nodeid] [dataset] [pincode] [discriminator]",
|
||||
.handler = controller_pairing_handler,
|
||||
},
|
||||
{
|
||||
.name = "group-settings",
|
||||
.description = "Managing the groups and keysets of the controller.\n"
|
||||
"\tUsage: controller group-settings <sub-commands>",
|
||||
.handler = controller_group_settings_handler,
|
||||
},
|
||||
{
|
||||
.name = "pairing",
|
||||
.description = "Pairing a node.\n"
|
||||
"\tUsage: controller pairing onnetwork [nodeid] [pincode] OR\n"
|
||||
"\tcontroller pairing ble-wifi [nodeid] [ssid] [password] [pincode] [discriminator] OR\n"
|
||||
"\tcontroller pairing ble-thread [nodeid] [dataset] [pincode] [discriminator]",
|
||||
.handler = controller_pairing_handler,
|
||||
},
|
||||
{
|
||||
.name = "group-settings",
|
||||
.description = "Managing the groups and keysets of the controller.\n"
|
||||
"\tUsage: controller group-settings <sub-commands>",
|
||||
.handler = controller_group_settings_handler,
|
||||
},
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
{
|
||||
.name = "invoke-cmd",
|
||||
.description =
|
||||
"Send command to the nodes.\n"
|
||||
"\tUsage: controller invoke-cmd [node-id|group-id] [endpoint-id] [cluster-id] [command-id] [payload]\n"
|
||||
"\tNotes: group-id should start with prefix '0xFFFFFFFFFFFF', endpoint-id will be ignored if the fist "
|
||||
"parameter is group-id.\n"
|
||||
"\tNotes: The payload should be a JSON object that includes all the command data fields defined in the "
|
||||
"SPEC. You can get the format of the payload from "
|
||||
"https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#cluster-commands",
|
||||
.handler = controller_invoke_command_handler,
|
||||
},
|
||||
{
|
||||
.name = "read-attr",
|
||||
.description = "Read attributes of the nodes.\n"
|
||||
"\tUsage: controller read-attr [node-id] [endpoint-id] [cluster-id] [attr-id]",
|
||||
.handler = controller_read_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "write-attr",
|
||||
.description = "Write attributes of the nodes.\n"
|
||||
"\tUsage: controller write-attr [node-id|group-id] [endpoint-id] [cluster-id] [attr-id] "
|
||||
"[attr-value]\n"
|
||||
"\tNotes: attr-value should be a JSON object that contains the attribute value JSON item."
|
||||
"You can get the format of the attr-value from "
|
||||
"https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#write-attribute-commands",
|
||||
.handler = controller_write_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "read-event",
|
||||
.description = "Read events of the nodes.\n"
|
||||
"\tUsage: controller read-event [node-id] [endpoint-id] [cluster-id] [event-id]",
|
||||
.handler = controller_read_event_handler,
|
||||
},
|
||||
{
|
||||
.name = "subs-attr",
|
||||
.description = "Subscribe attributes of the nodes.\n"
|
||||
"\tUsage: controller subs-attr [node-id] [endpoint-id] [cluster-id] [attr-id] "
|
||||
"[min-interval] [max-interval]",
|
||||
.handler = controller_subscribe_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "subs-event",
|
||||
.description = "Subscribe events of the nodes.\n"
|
||||
"\tUsage: controller subs-attr [node-id] [endpoint-id] [cluster-id] [event-id] "
|
||||
"[min-interval] [max-interval]",
|
||||
.handler = controller_subscribe_event_handler,
|
||||
},
|
||||
{
|
||||
.name = "shutdown-subs",
|
||||
.description = "Shutdown subscription.\n"
|
||||
"\tUsage: controller shutdown-subs [node-id] [subscription-id]",
|
||||
.handler = controller_shutdown_subscription_handler,
|
||||
},
|
||||
{
|
||||
.name = "invoke-cmd",
|
||||
.description =
|
||||
"Send command to the nodes.\n"
|
||||
"\tUsage: controller invoke-cmd [node-id|group-id] [endpoint-id] [cluster-id] [command-id] [payload]\n"
|
||||
"\tNotes: group-id should start with prefix '0xFFFFFFFFFFFF', endpoint-id will be ignored if the fist "
|
||||
"parameter is group-id.\n"
|
||||
"\tNotes: The payload should be a JSON object that includes all the command data fields defined in the "
|
||||
"SPEC. You can get the format of the payload from "
|
||||
"https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#cluster-commands",
|
||||
.handler = controller_invoke_command_handler,
|
||||
},
|
||||
{
|
||||
.name = "read-attr",
|
||||
.description = "Read attributes of the nodes.\n"
|
||||
"\tUsage: controller read-attr [node-id] [endpoint-id] [cluster-id] [attr-id]",
|
||||
.handler = controller_read_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "write-attr",
|
||||
.description =
|
||||
"Write attributes of the nodes.\n"
|
||||
"\tUsage: controller write-attr [node-id|group-id] [endpoint-id] [cluster-id] [attr-id] "
|
||||
"[attr-value]\n"
|
||||
"\tNotes: attr-value should be a JSON object that contains the attribute value JSON item."
|
||||
"You can get the format of the attr-value from "
|
||||
"https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#write-attribute-commands",
|
||||
.handler = controller_write_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "read-event",
|
||||
.description = "Read events of the nodes.\n"
|
||||
"\tUsage: controller read-event [node-id] [endpoint-id] [cluster-id] [event-id]",
|
||||
.handler = controller_read_event_handler,
|
||||
},
|
||||
{
|
||||
.name = "subs-attr",
|
||||
.description = "Subscribe attributes of the nodes.\n"
|
||||
"\tUsage: controller subs-attr [node-id] [endpoint-id] [cluster-id] [attr-id] "
|
||||
"[min-interval] [max-interval]",
|
||||
.handler = controller_subscribe_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "subs-event",
|
||||
.description = "Subscribe events of the nodes.\n"
|
||||
"\tUsage: controller subs-attr [node-id] [endpoint-id] [cluster-id] [event-id] "
|
||||
"[min-interval] [max-interval]",
|
||||
.handler = controller_subscribe_event_handler,
|
||||
},
|
||||
{
|
||||
.name = "shutdown-subs",
|
||||
.description = "Shutdown subscription.\n"
|
||||
"\tUsage: controller shutdown-subs [node-id] [subscription-id]",
|
||||
.handler = controller_shutdown_subscription_handler,
|
||||
},
|
||||
};
|
||||
|
||||
const static command_t controller_command = {
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2024 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <esp_check.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_matter_controller_credentials_issuer.h>
|
||||
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
|
||||
class example_credentials_issuer : public credentials_issuer {
|
||||
esp_err_t initialize_credentials_issuer(chip::PersistentStorageDelegate &storage) override
|
||||
{
|
||||
return m_operational_creds_issuer.Initialize(storage) == CHIP_NO_ERROR ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
chip::Controller::OperationalCredentialsDelegate *get_delegate() override { return &m_operational_creds_issuer; }
|
||||
|
||||
esp_err_t generate_controller_noc_chain(chip::NodeId node_id, chip::FabricId fabric_id,
|
||||
chip::Crypto::P256Keypair &keypair, chip::MutableByteSpan &rcac,
|
||||
chip::MutableByteSpan &icac, chip::MutableByteSpan &noc) override
|
||||
{
|
||||
CHIP_ERROR err = m_operational_creds_issuer.GenerateNOCChainAfterValidation(
|
||||
node_id, fabric_id, chip::kUndefinedCATs, keypair.Pubkey(), rcac, icac, noc);
|
||||
return err == CHIP_NO_ERROR ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
private:
|
||||
chip::Controller::ExampleOperationalCredentialsIssuer m_operational_creds_issuer;
|
||||
};
|
||||
|
||||
static credentials_issuer *s_custom_credentials_issuer = nullptr;
|
||||
|
||||
void set_custom_credentials_issuer(credentials_issuer *issuer)
|
||||
{
|
||||
s_custom_credentials_issuer = issuer;
|
||||
}
|
||||
|
||||
credentials_issuer *get_credentials_issuer()
|
||||
{
|
||||
#ifdef CONFIG_TEST_OPERATIONAL_CREDS_ISSUER
|
||||
static example_credentials_issuer s_creds_issuer;
|
||||
return &s_creds_issuer;
|
||||
#elif defined(CONFIG_CUSTOM_OPERATIONAL_CREDS_ISSUER)
|
||||
return s_custom_credentials_issuer;
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright 2024 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <esp_check.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
#include <controller/ExampleOperationalCredentialsIssuer.h>
|
||||
#include <controller/OperationalCredentialsDelegate.h>
|
||||
#include <crypto/CHIPCryptoPAL.h>
|
||||
#include <lib/core/CHIPPersistentStorageDelegate.h>
|
||||
#include <lib/core/DataModelTypes.h>
|
||||
#include <lib/core/NodeId.h>
|
||||
#include <lib/support/Span.h>
|
||||
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
class credentials_issuer {
|
||||
public:
|
||||
virtual ~credentials_issuer() {}
|
||||
|
||||
/**
|
||||
* This function is used to initialize the Credentials Issuer, if needed.
|
||||
*
|
||||
* @param[in] storage A reference to the storage, where the Credentials Issuer can optionally use to access the
|
||||
* keypair in storage.
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
virtual esp_err_t initialize_credentials_issuer(chip::PersistentStorageDelegate &storage) = 0;
|
||||
|
||||
/**
|
||||
* This function is used to get the OperationalCredentialsDelegate which is used to generate NOC chains for End
|
||||
* Devices
|
||||
*
|
||||
* @return OperationalCredentialsDelegate of the Controller/Commissioner
|
||||
*/
|
||||
virtual chip::Controller::OperationalCredentialsDelegate *get_delegate() = 0;
|
||||
|
||||
/**
|
||||
* This function is used to Generate NOC Chain for the Controller/Commissioner.
|
||||
*
|
||||
* @param[in] nodeId The desired NodeId for the generated NOC Chain - May be optional/unused in some
|
||||
* implementations.
|
||||
* @param[in] fabricId The desired FabricId for the generated NOC Chain - May be optional/unused in some
|
||||
* implementations.
|
||||
* @param[in] keypair The desired Keypair for the generated NOC Chain - May be optional/unused in some
|
||||
* implementations.
|
||||
* @param[in,out] rcac Buffer to hold the Root Certificate of the generated NOC Chain.
|
||||
* @param[in,out] icac Buffer to hold the Intermediate Certificate of the generated NOC Chain.
|
||||
* @param[in,out] noc Buffer to hold the Leaf Certificate of the generated NOC Chain.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
virtual esp_err_t generate_controller_noc_chain(chip::NodeId node_id, chip::FabricId fabric,
|
||||
chip::Crypto::P256Keypair &keypair, chip::MutableByteSpan &rcac,
|
||||
chip::MutableByteSpan &icac, chip::MutableByteSpan &noc) = 0;
|
||||
};
|
||||
|
||||
void set_custom_credentials_issuer(credentials_issuer *issuer);
|
||||
|
||||
credentials_issuer *get_credentials_issuer();
|
||||
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
+56
-10
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <esp_check.h>
|
||||
#include <esp_matter_commissioner.h>
|
||||
#include <esp_matter_controller_client.h>
|
||||
#include <esp_matter_controller_group_settings.h>
|
||||
#include <esp_matter_controller_utils.h>
|
||||
|
||||
@@ -49,7 +49,12 @@ esp_err_t show_groups()
|
||||
ESP_LOGI(TAG, " | Available Groups : |");
|
||||
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
|
||||
ESP_LOGI(TAG, " | Group Id | KeySet Id | Group Name |");
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
FabricIndex fabric_index =
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_controller()->GetFabricIndex();
|
||||
#endif
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
auto iter = group_data_provider->IterateGroupInfo(fabric_index);
|
||||
GroupDataProvider::GroupInfo group_info;
|
||||
@@ -74,7 +79,12 @@ esp_err_t add_group(char *group_name, uint16_t group_id)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
FabricIndex fabric_index =
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_controller()->GetFabricIndex();
|
||||
#endif
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
GroupDataProvider::GroupInfo group_info;
|
||||
|
||||
@@ -91,7 +101,12 @@ esp_err_t remove_group(uint16_t group_id)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
FabricIndex fabric_index =
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_controller()->GetFabricIndex();
|
||||
#endif
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->RemoveGroupInfo(fabric_index, group_id), ESP_FAIL, TAG,
|
||||
"Failed to remove the group info");
|
||||
@@ -100,7 +115,12 @@ esp_err_t remove_group(uint16_t group_id)
|
||||
|
||||
esp_err_t show_keysets()
|
||||
{
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
FabricIndex fabric_index =
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_controller()->GetFabricIndex();
|
||||
#endif
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
GroupDataProvider::KeySet keyset;
|
||||
|
||||
@@ -125,7 +145,12 @@ esp_err_t show_keysets()
|
||||
esp_err_t bind_keyset(uint16_t group_id, uint16_t keyset_id)
|
||||
{
|
||||
size_t current_count = 0;
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
FabricIndex fabric_index =
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_controller()->GetFabricIndex();
|
||||
#endif
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
|
||||
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
|
||||
@@ -144,7 +169,12 @@ esp_err_t bind_keyset(uint16_t group_id, uint16_t keyset_id)
|
||||
esp_err_t unbind_keyset(uint16_t group_id, uint16_t keyset_id)
|
||||
{
|
||||
size_t index = 0;
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
FabricIndex fabric_index =
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_controller()->GetFabricIndex();
|
||||
#endif
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
|
||||
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
|
||||
@@ -165,12 +195,23 @@ esp_err_t unbind_keyset(uint16_t group_id, uint16_t keyset_id)
|
||||
|
||||
esp_err_t add_keyset(uint16_t keyset_id, uint8_t key_policy, uint64_t validity_time, char *epoch_key_oct_str)
|
||||
{
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
|
||||
FabricIndex fabric_index =
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
controller_instance.get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
controller_instance.get_controller()->GetFabricIndex();
|
||||
#endif
|
||||
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
uint8_t compressed_fabric_id[sizeof(uint64_t)];
|
||||
chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
|
||||
if (CHIP_NO_ERROR !=
|
||||
commissioner::get_device_commissioner()->GetCompressedFabricIdBytes(compressed_fabric_id_span)) {
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
controller_instance.get_commissioner()->GetCompressedFabricIdBytes(compressed_fabric_id_span)) {
|
||||
#else
|
||||
controller_instance.get_controller()->GetCompressedFabricIdBytes(compressed_fabric_id_span)) {
|
||||
#endif
|
||||
ESP_LOGE(TAG, "Failed to get the compressed fabric_id");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -197,7 +238,12 @@ esp_err_t add_keyset(uint16_t keyset_id, uint8_t key_policy, uint64_t validity_t
|
||||
|
||||
esp_err_t remove_keyset(uint16_t keyset_id)
|
||||
{
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
FabricIndex fabric_index =
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_commissioner()->GetFabricIndex();
|
||||
#else
|
||||
esp_matter::controller::matter_controller_client::get_instance().get_controller()->GetFabricIndex();
|
||||
#endif
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
|
||||
size_t index = 0;
|
||||
+61
@@ -18,21 +18,82 @@
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
namespace group_settings {
|
||||
/** Group management functions for the client only controller **/
|
||||
|
||||
/**
|
||||
* Print groups information
|
||||
*/
|
||||
esp_err_t show_groups();
|
||||
|
||||
/**
|
||||
* Add a group
|
||||
*
|
||||
* @param[in] group_name Group name
|
||||
* @param[in] group_id Group ID
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t add_group(char *group_name, uint16_t group_id);
|
||||
|
||||
/**
|
||||
* Leave a group
|
||||
*
|
||||
* @param[in] group_id Group ID
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t remove_group(uint16_t group_id);
|
||||
|
||||
/**
|
||||
* Print group keysets
|
||||
*/
|
||||
esp_err_t show_keysets();
|
||||
|
||||
/**
|
||||
* Bind a group keyset to a group
|
||||
*
|
||||
* @param[in] group_id Group ID
|
||||
* @param[in] keyset_id Group Keyset ID
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t bind_keyset(uint16_t group_id, uint16_t keyset_id);
|
||||
|
||||
/**
|
||||
* Unbind a group keyset to a group
|
||||
*
|
||||
* @param[in] group_id Group ID
|
||||
* @param[in] keyset_id Group Keyset ID
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t unbind_keyset(uint16_t group_id, uint16_t keyset_id);
|
||||
|
||||
/**
|
||||
* Add a group keyset
|
||||
*
|
||||
* @param[in] keyset_id Group Keyset ID
|
||||
* @param[in] key_policy Key policy
|
||||
* @param[in] validity_time Validity time for the keyset in second
|
||||
* @param[in] epoch_key_oct_str Octet string of the Epoch key
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t add_keyset(uint16_t keyset_id, uint8_t key_policy, uint64_t validity_time, char *epoch_key_oct_str);
|
||||
|
||||
/**
|
||||
* Remove a group keyset
|
||||
*
|
||||
* @param[in] keyset_id Group Keyset ID
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return error in case of failure
|
||||
*/
|
||||
esp_err_t remove_keyset(uint16_t keyset_id);
|
||||
|
||||
} // namespace group_settings
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
|
||||
#if !CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
uint8_t s_controller_fabric_index = chip::kUndefinedFabricIndex;
|
||||
|
||||
void set_fabric_index(uint8_t fabric_index)
|
||||
@@ -30,7 +30,7 @@ uint8_t get_fabric_index(void)
|
||||
{
|
||||
return s_controller_fabric_index;
|
||||
}
|
||||
#endif // !CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
+9
-8
@@ -16,14 +16,14 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <app/ConcreteAttributePath.h>
|
||||
#include <app/AttributePathParams.h>
|
||||
#include <app/ConcreteAttributePath.h>
|
||||
#include <app/EventHeader.h>
|
||||
#include <lib/core/TLVReader.h>
|
||||
|
||||
using chip::Platform::ScopedMemoryBufferWithSize;
|
||||
using chip::app::AttributePathParams;
|
||||
using chip::app::EventPathParams;
|
||||
using chip::Platform::ScopedMemoryBufferWithSize;
|
||||
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
@@ -33,15 +33,16 @@ using event_report_cb_t = void (*)(uint64_t remote_node_id, const chip::app::Eve
|
||||
chip::TLV::TLVReader *data);
|
||||
using subscribe_done_cb_t = void (*)(uint64_t remote_node_id, uint32_t subscription_id);
|
||||
using subscribe_failure_cb_t = void (*)(void *subscribe_command);
|
||||
using read_done_cb_t = void (*)(uint64_t remote_node_id, const ScopedMemoryBufferWithSize<AttributePathParams> &attr_paths,
|
||||
using read_done_cb_t = void (*)(uint64_t remote_node_id,
|
||||
const ScopedMemoryBufferWithSize<AttributePathParams> &attr_paths,
|
||||
const ScopedMemoryBufferWithSize<EventPathParams> &EventPathParams);
|
||||
|
||||
#if !CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#if CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
/**
|
||||
* @brief Set the fabric index of the controller.
|
||||
* The controller should be able to send commands to the devices on this fabric.
|
||||
*
|
||||
* This should be called after the controller is added to the fabric.
|
||||
* If Matter server is enabled on the controller, the controller could join multiple fabrics.
|
||||
* We should choose one on which the controller is able to send commands to other end-devices.
|
||||
* This should be called after the controller server is added to the fabric.
|
||||
*/
|
||||
void set_fabric_index(uint8_t fabric_index);
|
||||
|
||||
@@ -50,7 +51,7 @@ void set_fabric_index(uint8_t fabric_index);
|
||||
*
|
||||
*/
|
||||
uint8_t get_fabric_index();
|
||||
#endif // !CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
@@ -1,247 +0,0 @@
|
||||
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <app/clusters/network-commissioning/network-commissioning.h>
|
||||
#include <app/server/Dnssd.h>
|
||||
#include <app/server/OnboardingCodesUtil.h>
|
||||
#include <app/server/Server.h>
|
||||
#include <controller/CHIPDeviceControllerFactory.h>
|
||||
#include <controller/ExampleOperationalCredentialsIssuer.h>
|
||||
#include <credentials/GroupDataProviderImpl.h>
|
||||
#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
|
||||
#include <crypto/CHIPCryptoPAL.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_matter_attestation_trust_store.h>
|
||||
#include <esp_matter_commissioner.h>
|
||||
#include <esp_matter_controller_pairing_command.h>
|
||||
#include <lib/support/TestGroupData.h>
|
||||
#include <platform/DeviceInstanceInfoProvider.h>
|
||||
#include <platform/DiagnosticDataProvider.h>
|
||||
|
||||
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
#include <platform/internal/BLEManager.h>
|
||||
#include <platform/ESP32/BLEManagerImpl.h>
|
||||
#endif
|
||||
|
||||
using namespace chip;
|
||||
using namespace chip::Credentials;
|
||||
using namespace chip::DeviceLayer;
|
||||
using namespace chip::Inet;
|
||||
using namespace chip::Transport;
|
||||
using namespace chip::app::Clusters;
|
||||
using namespace chip::Controller;
|
||||
using namespace chip::Messaging;
|
||||
using namespace esp_matter::controller;
|
||||
|
||||
class ControllerServerStorageDelegate : public PersistentStorageDelegate {
|
||||
CHIP_ERROR SyncGetKeyValue(const char *key, void *buffer, uint16_t &size) override
|
||||
{
|
||||
ChipLogProgress(AppServer, "Retrieving value from controller server storage.");
|
||||
size_t bytesRead = 0;
|
||||
CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size, &bytesRead);
|
||||
|
||||
if (err == CHIP_NO_ERROR) {
|
||||
ChipLogProgress(AppServer, "Retrieved value from server storage.");
|
||||
}
|
||||
size = static_cast<uint16_t>(bytesRead);
|
||||
return err;
|
||||
}
|
||||
|
||||
CHIP_ERROR SyncSetKeyValue(const char *key, const void *value, uint16_t size) override
|
||||
{
|
||||
ChipLogProgress(AppServer, "Stored value in server storage");
|
||||
return PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
|
||||
}
|
||||
|
||||
CHIP_ERROR SyncDeleteKeyValue(const char *key) override
|
||||
{
|
||||
ChipLogProgress(AppServer, "Delete value in server storage");
|
||||
return PersistedStorage::KeyValueStoreMgr().Delete(key);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr uint64_t LOCAL_NODE_ID = 112233;
|
||||
|
||||
ControllerServerStorageDelegate controller_server_storage;
|
||||
ExampleOperationalCredentialsIssuer op_creds_issuer;
|
||||
NodeId local_node_id = LOCAL_NODE_ID;
|
||||
Credentials::GroupDataProviderImpl group_data_provider;
|
||||
AutoCommissioner auto_commissioner;
|
||||
|
||||
class ESPCommissionerCallback : public CommissionerCallback {
|
||||
void ReadyForCommissioning(uint32_t pincode, uint16_t discriminator, PeerAddress peerAddress) override
|
||||
{
|
||||
esp_matter::controller::pairing_on_network(pincode, pairing_command::get_instance().m_remote_node_id);
|
||||
}
|
||||
};
|
||||
|
||||
ESPCommissionerCallback commissioner_callback;
|
||||
DeviceCommissioner device_commissioner;
|
||||
CommissionerDiscoveryController commissioner_discovery_controller;
|
||||
Crypto::RawKeySessionKeystore session_keystore;
|
||||
|
||||
constexpr uint16_t kUdcListenPort = 5560;
|
||||
|
||||
namespace esp_matter {
|
||||
namespace commissioner {
|
||||
esp_err_t init(uint16_t commissioner_port)
|
||||
{
|
||||
#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
CHIP_ERROR err = chip::DeviceLayer::Internal::BLEMgr().Init();
|
||||
err = chip::DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(0, true);
|
||||
|
||||
if (err != CHIP_NO_ERROR) {
|
||||
ChipLogError(DeviceLayer, "BLEManager initialization failed: %s", ErrorStr(err));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
Controller::FactoryInitParams factoryParams;
|
||||
Controller::SetupParams setupParams;
|
||||
|
||||
// use a different listen port for the commissioner
|
||||
factoryParams.listenPort = commissioner_port;
|
||||
factoryParams.fabricIndependentStorage = &controller_server_storage;
|
||||
factoryParams.fabricTable = &Server::GetInstance().GetFabricTable();
|
||||
factoryParams.sessionKeystore = &session_keystore;
|
||||
|
||||
group_data_provider.SetStorageDelegate(&controller_server_storage);
|
||||
group_data_provider.SetSessionKeystore(factoryParams.sessionKeystore);
|
||||
if (group_data_provider.Init() != CHIP_NO_ERROR) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
factoryParams.groupDataProvider = reinterpret_cast<Credentials::GroupDataProvider *>(&group_data_provider);
|
||||
|
||||
setupParams.operationalCredentialsDelegate = &op_creds_issuer;
|
||||
uint16_t vendor_id;
|
||||
DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendor_id);
|
||||
ChipLogProgress(Support, " ----- Commissioner using vendorId 0x%04X", vendor_id);
|
||||
setupParams.controllerVendorId = static_cast<VendorId>(vendor_id);
|
||||
|
||||
if (op_creds_issuer.Initialize(controller_server_storage) != CHIP_NO_ERROR) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ChipLogProgress(Support, " ----- UDC listening on port %d", kUdcListenPort);
|
||||
if (device_commissioner.SetUdcListenPort(kUdcListenPort) != CHIP_NO_ERROR) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
const Credentials::AttestationTrustStore *testingRootStore = Credentials::get_attestation_trust_store();
|
||||
SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
|
||||
|
||||
Platform::ScopedMemoryBuffer<uint8_t> noc;
|
||||
if (!noc.Alloc(Controller::kMaxCHIPDERCertLength)) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
MutableByteSpan nocSpan(noc.Get(), Controller::kMaxCHIPDERCertLength);
|
||||
|
||||
Platform::ScopedMemoryBuffer<uint8_t> icac;
|
||||
if (!icac.Alloc(Controller::kMaxCHIPDERCertLength)) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
MutableByteSpan icacSpan(icac.Get(), Controller::kMaxCHIPDERCertLength);
|
||||
|
||||
Platform::ScopedMemoryBuffer<uint8_t> rcac;
|
||||
if (!rcac.Alloc(Controller::kMaxCHIPDERCertLength)) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
MutableByteSpan rcacSpan(rcac.Get(), Controller::kMaxCHIPDERCertLength);
|
||||
|
||||
Crypto::P256Keypair ephemeralKey;
|
||||
if (ephemeralKey.Initialize(Crypto::ECPKeyTarget::ECDSA) != CHIP_NO_ERROR) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (op_creds_issuer.GenerateNOCChainAfterValidation(local_node_id, /* fabricId = */ 1, chip::kUndefinedCATs,
|
||||
ephemeralKey.Pubkey(), rcacSpan, icacSpan,
|
||||
nocSpan) != CHIP_NO_ERROR) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
setupParams.operationalKeypair = &ephemeralKey;
|
||||
setupParams.controllerRCAC = rcacSpan;
|
||||
setupParams.controllerICAC = icacSpan;
|
||||
setupParams.controllerNOC = nocSpan;
|
||||
setupParams.defaultCommissioner = &auto_commissioner;
|
||||
|
||||
auto &factory = Controller::DeviceControllerFactory::GetInstance();
|
||||
if (factory.Init(factoryParams) != CHIP_NO_ERROR) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (factory.SetupCommissioner(setupParams, *get_device_commissioner()) != CHIP_NO_ERROR) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
FabricIndex fabricIndex = device_commissioner.GetFabricIndex();
|
||||
if (fabricIndex == kUndefinedFabricIndex) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
uint8_t compressedFabricId[sizeof(uint64_t)] = {0};
|
||||
MutableByteSpan compressedFabricIdSpan(compressedFabricId);
|
||||
if (device_commissioner.GetCompressedFabricIdBytes(compressedFabricIdSpan) != CHIP_NO_ERROR) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ChipLogProgress(Support, "Setting up group data for Fabric Index %u with Compressed Fabric ID:",
|
||||
static_cast<unsigned>(fabricIndex));
|
||||
ChipLogByteSpan(Support, compressedFabricIdSpan);
|
||||
|
||||
// TODO: Once ExampleOperationalCredentialsIssuer has support, set default IPK on it as well so
|
||||
// that commissioned devices get the IPK set from real values rather than "test-only" internal hookups.
|
||||
ByteSpan defaultIpk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
|
||||
if (CHIP_NO_ERROR !=
|
||||
chip::Credentials::SetSingleIpkEpochKey(reinterpret_cast<GroupDataProvider *>(&group_data_provider),
|
||||
fabricIndex, defaultIpk, compressedFabricIdSpan)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
get_discovery_controller()->SetUserDirectedCommissioningServer(
|
||||
get_device_commissioner()->GetUserDirectedCommissioningServer());
|
||||
get_discovery_controller()->SetCommissionerCallback(&commissioner_callback);
|
||||
|
||||
get_device_commissioner()->RegisterPairingDelegate(&pairing_command::get_instance());
|
||||
|
||||
ChipLogProgress(Support, "InitCommissioner nodeId=0x" ChipLogFormatX64 " fabricIndex=0x%x",
|
||||
ChipLogValueX64(get_device_commissioner()->GetNodeId()), static_cast<unsigned>(fabricIndex));
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
UserDirectedCommissioningServer *udcServer = get_device_commissioner()->GetUserDirectedCommissioningServer();
|
||||
if (udcServer != nullptr) {
|
||||
udcServer->SetUserConfirmationProvider(nullptr);
|
||||
}
|
||||
|
||||
get_device_commissioner()->Shutdown();
|
||||
}
|
||||
|
||||
DeviceCommissioner *get_device_commissioner()
|
||||
{
|
||||
return &device_commissioner;
|
||||
}
|
||||
|
||||
CommissionerDiscoveryController *get_discovery_controller()
|
||||
{
|
||||
return &commissioner_discovery_controller;
|
||||
}
|
||||
|
||||
AutoCommissioner *get_auto_commissioner()
|
||||
{
|
||||
return &auto_commissioner;
|
||||
}
|
||||
|
||||
} // namespace commissioner
|
||||
} // namespace esp_matter
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <controller/CHIPDeviceController.h>
|
||||
#include <controller/CommissionerDiscoveryController.h>
|
||||
#include <credentials/DeviceAttestationCredsProvider.h>
|
||||
#include <lib/core/CHIPError.h>
|
||||
#include <platform/CHIPDeviceLayer.h>
|
||||
#include <platform/PlatformManager.h>
|
||||
#include <transport/TransportMgr.h>
|
||||
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
using chip::NodeId;
|
||||
using chip::Controller::AutoCommissioner;
|
||||
using chip::Controller::DeviceCommissioner;
|
||||
using chip::Controller::DevicePairingDelegate;
|
||||
using chip::Transport::PeerAddress;
|
||||
|
||||
namespace esp_matter {
|
||||
namespace commissioner {
|
||||
|
||||
esp_err_t init(uint16_t commissioner_port);
|
||||
void shutdown();
|
||||
|
||||
DeviceCommissioner *get_device_commissioner();
|
||||
CommissionerDiscoveryController *get_discovery_controller();
|
||||
AutoCommissioner *get_auto_commissioner();
|
||||
} // namespace commissioner
|
||||
} // namespace esp_matter
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
@@ -37,11 +37,6 @@ project(controller)
|
||||
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H" APPEND)
|
||||
idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND)
|
||||
|
||||
if (CONFIG_ESP_MATTER_COMMISSIONER_ENABLE)
|
||||
idf_build_set_property(CXX_COMPILE_OPTIONS "-DCHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY=1;-DCHIP_CONFIG_CONTROLLER_MAX_ACTIVE_DEVICES=${CONFIG_ESP_MATTER_COMMISSIONER_MAX_ACTIVE_DEVICES}" APPEND)
|
||||
idf_build_set_property(C_COMPILE_OPTIONS "-DCHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY=1;-DCHIP_CONFIG_CONTROLLER_MAX_ACTIVE_DEVICES=${CONFIG_ESP_MATTER_COMMISSIONER_MAX_ACTIVE_DEVICES}" APPEND)
|
||||
endif()
|
||||
|
||||
# For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various
|
||||
# flags that depend on -Wformat
|
||||
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND)
|
||||
|
||||
@@ -38,10 +38,10 @@ idf.py -p <PORT> erase-flash flash monitor
|
||||
|
||||
### 4.3 Pair and Control
|
||||
|
||||
- Pairing the controller with chip-tool
|
||||
- Connect the controller to Wi-Fi network with the device console
|
||||
|
||||
```
|
||||
./chip-tool pairing ble-wifi 0x7483 <ssid> <password> 20202021 3840
|
||||
matter esp wifi connect {ssid} {password}
|
||||
```
|
||||
|
||||
- Initializing a new Thread network dataset and commit it as the active one
|
||||
@@ -64,17 +64,16 @@ matter esp ot_cli ifconfig up
|
||||
matter esp ot_cli thread start
|
||||
```
|
||||
|
||||
- Pairing the Thread end-device with chip-tool and write the ACL
|
||||
- Pairing the Thread end-device
|
||||
|
||||
```
|
||||
./chip-tool pairing ble-thread 0x7484 hex:<dataset_tlvs> 20202021 3840
|
||||
./chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233, 25731], "targets":null}]' 0x7484 0
|
||||
matter esp controller pairing ble-thread 1234 <dataset_tlvs> 20202021 3840
|
||||
```
|
||||
|
||||
- Control the Thread end-device on the device console (On/Off cluster Toggle command)
|
||||
|
||||
```
|
||||
matter esp controller invoke-cmd 0x7484 1 6 2
|
||||
matter esp controller invoke-cmd 1234 1 6 2
|
||||
```
|
||||
|
||||
## A1 Appendix FAQs
|
||||
|
||||
@@ -11,15 +11,11 @@
|
||||
#include <nvs_flash.h>
|
||||
|
||||
#include <esp_matter.h>
|
||||
#include <esp_matter_commissioner.h>
|
||||
#include <esp_matter_controller_client.h>
|
||||
#include <esp_matter_console.h>
|
||||
#include <esp_matter_controller_console.h>
|
||||
#include <esp_matter_controller_utils.h>
|
||||
#include <esp_matter_ota.h>
|
||||
#if CONFIG_ESP_MATTER_CONTROLLER_CUSTOM_CLUSTER_ENABLE
|
||||
#include <matter_controller_cluster.h>
|
||||
#include <matter_controller_device_mgr.h>
|
||||
#endif // CONFIG_ESP_MATTER_CONTROLLER_CUSTOM_CLUSTER_ENABLE
|
||||
#if CONFIG_OPENTHREAD_BORDER_ROUTER
|
||||
#include <esp_matter_thread_br_console.h>
|
||||
#include <esp_matter_thread_br_launcher.h>
|
||||
@@ -53,14 +49,8 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)
|
||||
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
|
||||
.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),
|
||||
};
|
||||
printf("init thread br\n");
|
||||
esp_matter::thread_br_init(&config);
|
||||
#endif
|
||||
#if !CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
// Check whether fabric exists at index 1, if yes, set the controller fabric index to 1.
|
||||
// If you controller works on other fabrics, please set the fabric index to another value.
|
||||
if (chip::Server::GetInstance().GetFabricTable().FindFabricWithIndex(1)) {
|
||||
esp_matter::controller::set_fabric_index(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -86,22 +76,14 @@ extern "C" void app_main()
|
||||
esp_matter::console::thread_br_cli_register_command();
|
||||
#endif // CONFIG_OPENTHREAD_BORDER_ROUTER && CONFIG_OPENTHREAD_CLI
|
||||
#endif // CONFIG_ENABLE_CHIP_SHELL
|
||||
#if !CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
// If there is no commissioner in the controller, we need a default node so that the controller can be commissioned
|
||||
// to a specific fabric.
|
||||
node::config_t node_config;
|
||||
node_t *node = node::create(&node_config, NULL, NULL);
|
||||
ABORT_APP_ON_FAILURE(node != nullptr, ESP_LOGE(TAG, "Failed to create Matter node"));
|
||||
|
||||
#endif // !CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
|
||||
/* Matter start */
|
||||
err = esp_matter::start(app_event_cb);
|
||||
ABORT_APP_ON_FAILURE(err == ESP_OK, ESP_LOGE(TAG, "Failed to start Matter, err:%d", err));
|
||||
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
esp_matter::lock::chip_stack_lock(portMAX_DELAY);
|
||||
esp_matter::commissioner::init(5580);
|
||||
esp_matter::controller::matter_controller_client::get_instance().init(112233, 1, 5580);
|
||||
esp_matter::controller::matter_controller_client::get_instance().setup_commissioner();
|
||||
esp_matter::lock::chip_stack_unlock();
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
{ \
|
||||
.radio_mode = RADIO_MODE_UART_RCP, \
|
||||
.radio_uart_config = { \
|
||||
.port = 1, \
|
||||
.port = UART_NUM_1, \
|
||||
.uart_config = \
|
||||
{ \
|
||||
.baud_rate = 460800, \
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <sdkconfig.h>
|
||||
|
||||
#ifndef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
|
||||
#ifdef CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
// Enable or disable whether this device advertises as a commissioner.
|
||||
#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY 1
|
||||
#endif // CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
|
||||
// Number of devices a controller can be simultaneously connected to
|
||||
#define CHIP_CONFIG_CONTROLLER_MAX_ACTIVE_DEVICES 8
|
||||
|
||||
#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
|
||||
@@ -50,3 +50,6 @@ CONFIG_MBEDTLS_HKDF_C=y
|
||||
# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1)
|
||||
# unique local addresses for fabrics(MAX_FABRIC), a link local address(1)
|
||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
|
||||
|
||||
# Enable project configurations
|
||||
CONFIG_CHIP_PROJECT_CONFIG="main/matter_project_config.h"
|
||||
|
||||
@@ -5,3 +5,6 @@ CONFIG_ENABLE_ESP32_BLE_CONTROLLER=y
|
||||
|
||||
# Disable using ble for commissioning
|
||||
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n
|
||||
|
||||
# Disable Matter server
|
||||
CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER=n
|
||||
|
||||
@@ -44,9 +44,10 @@ CONFIG_MDNS_MULTIPLE_INSTANCE=y
|
||||
# Enable chip shell
|
||||
CONFIG_ENABLE_CHIP_SHELL=y
|
||||
CONFIG_ESP_MATTER_CONSOLE_TASK_STACK=4096
|
||||
CONFIG_CHIP_SHELL_CMD_LINE_BUF_MAX_LENGTH=512
|
||||
|
||||
# Increase Stack size
|
||||
CONFIG_CHIP_TASK_STACK_SIZE=10240
|
||||
CONFIG_CHIP_TASK_STACK_SIZE=15360
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||
|
||||
# Wi-Fi Settings
|
||||
@@ -54,8 +55,10 @@ CONFIG_ENABLE_WIFI_STATION=y
|
||||
CONFIG_ENABLE_WIFI_AP=n
|
||||
|
||||
# Enable Controller and disable commissioner
|
||||
CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER=n
|
||||
CONFIG_ENABLE_CHIP_CONTROLLER_BUILD=y
|
||||
CONFIG_ESP_MATTER_CONTROLLER_ENABLE=y
|
||||
CONFIG_ESP_MATTER_COMMISSIONER_ENABLE=n
|
||||
CONFIG_ESP_MATTER_COMMISSIONER_ENABLE=y
|
||||
CONFIG_ESP_MATTER_CONTROLLER_CUSTOM_CLUSTER_ENABLE=n
|
||||
|
||||
# Disable chip test build
|
||||
@@ -72,3 +75,17 @@ CONFIG_ENABLE_ROUTE_HOOK=n
|
||||
|
||||
# Use USB Jtag Console
|
||||
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
|
||||
|
||||
# Enable project configurations
|
||||
CONFIG_CHIP_PROJECT_CONFIG="main/matter_project_config.h"
|
||||
|
||||
# Enable ble controller
|
||||
CONFIG_ENABLE_ESP32_BLE_CONTROLLER=y
|
||||
|
||||
# SPIRAM
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_SPEED_80M=y
|
||||
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=512
|
||||
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192
|
||||
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
|
||||
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
|
||||
|
||||
Reference in New Issue
Block a user